From d3d6cd6e1b1b54b16cf9758dfda84b67250c2325 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 20 Jul 2013 12:04:29 -0700 Subject: [PATCH 001/276] Small fixes in demo --- demos/other/dynamic.html | 30 +++++++++--------------------- demos/other/webGLRenderer.html | 4 ++-- 2 files changed, 11 insertions(+), 23 deletions(-) diff --git a/demos/other/dynamic.html b/demos/other/dynamic.html index ccacd23..5517832 100644 --- a/demos/other/dynamic.html +++ b/demos/other/dynamic.html @@ -75,8 +75,7 @@ dragCoeff : 0.02, gravity : -1.2 }); - - // var graphics = Viva.Graph.View.cssGraphics(); + var graphics = Viva.Graph.View.svgGraphics(); graphics.node(function(node){ return Viva.Graph.svg('rect') @@ -89,7 +88,7 @@ { layout : layout, graphics : graphics, - container : document.getElementById('graph1'), + container : document.getElementById('graphConainer'), renderLinks : true }); @@ -100,30 +99,19 @@ } - - -
- - + + +
+ + \ No newline at end of file diff --git a/demos/other/webGLRenderer.html b/demos/other/webGLRenderer.html index 530306a..c2330cc 100644 --- a/demos/other/webGLRenderer.html +++ b/demos/other/webGLRenderer.html @@ -13,7 +13,7 @@ //var graph = graphGenerator.randomNoLinks(500); //var graph = graphGenerator.completeBipartite(100, 1); //var graph = graphGenerator.complete(2); - var graph = graphGenerator.grid(50, 50); + var graph = graphGenerator.grid(100, 100); //var graph = graphGenerator.balancedBinTree(10); //var graph = graphGenerator.ladder(1000); //var graph = Viva.Graph.graph(); @@ -22,7 +22,7 @@ var layout = Viva.Graph.Layout.forceDirected(graph, { springLength : 30, springCoeff : 0.0008, - dragCoeff : 0.00, + dragCoeff : 0.01, gravity : -1.2, theta : 1 }); From e0672809914c8325c4ccdc8f3ec19aa40a8a6c6f Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 20 Jul 2013 13:17:50 -0700 Subject: [PATCH 002/276] added simple layout perf test --- unit_tests/perf/perf_test.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 unit_tests/perf/perf_test.js diff --git a/unit_tests/perf/perf_test.js b/unit_tests/perf/perf_test.js new file mode 100644 index 0000000..283f4c7 --- /dev/null +++ b/unit_tests/perf/perf_test.js @@ -0,0 +1,18 @@ +var Viva = require('../../dist/vivagraph'); +var gridSize = 100; +var layoutIterations = 100; + +console.log('This is a very basic performance test of force directed layout'); +console.log('Constructing graph: Grid ' + gridSize + 'x' + gridSize); +var generator = Viva.Graph.generator(); +var graph = generator.grid(gridSize, gridSize); +console.log('Nodes: ' + graph.getNodesCount() + ', Edges: ' + graph.getLinksCount()); + +console.time('Layout time'); +console.log('Performing ' + layoutIterations + ' iterations of layout'); +var layout = Viva.Graph.Layout.forceDirected(graph); +for (var i = 0; i < layoutIterations; ++i) { + layout.step(); +} +console.timeEnd('Layout time'); +console.log('Done.'); From 6a04c5c5344b84baa377022ed65cacbd3203c913 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 20 Jul 2013 14:12:41 -0700 Subject: [PATCH 003/276] Latest v8 is awesome. 35% performance improvement. --- unit_tests/perf/perf_test.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/unit_tests/perf/perf_test.js b/unit_tests/perf/perf_test.js index 283f4c7..44829af 100644 --- a/unit_tests/perf/perf_test.js +++ b/unit_tests/perf/perf_test.js @@ -1,12 +1,21 @@ +// When node is compiled with the lates v8 version performance gain is 35% .. 40% +// +// Take a loook: +// V8 version: 3.20.2 (node version v0.11.5-pre+) +// Grid 100x100, Nodes: 10000, Edges: 19800, 100 layout iterations. Layout time: 9141ms +// +// V8 version: 3.14.5.9 (node version v0.10.10) +// Grid 100x100, Nodes: 10000, Edges: 19800, 100 layout iterations. Layout time: 14771ms + var Viva = require('../../dist/vivagraph'); var gridSize = 100; var layoutIterations = 100; console.log('This is a very basic performance test of force directed layout'); -console.log('Constructing graph: Grid ' + gridSize + 'x' + gridSize); +console.log('V8 version: ' + process.versions.v8); var generator = Viva.Graph.generator(); var graph = generator.grid(gridSize, gridSize); -console.log('Nodes: ' + graph.getNodesCount() + ', Edges: ' + graph.getLinksCount()); +console.log('Grid ' + gridSize + 'x' + gridSize + ', Nodes: ' + graph.getNodesCount() + ', Edges: ' + graph.getLinksCount()); console.time('Layout time'); console.log('Performing ' + layoutIterations + ' iterations of layout'); @@ -16,3 +25,4 @@ for (var i = 0; i < layoutIterations; ++i) { } console.timeEnd('Layout time'); console.log('Done.'); + From 43b524b1d4236a3a8bb091704d188cc5d10a9e02 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 20 Jul 2013 15:28:45 -0700 Subject: [PATCH 004/276] Layout now listens to graph changes events (no dependency on renderer) --- src/Layout/constant.js | 28 +++-- src/Layout/forceDirected.js | 187 ++++++++++++++++------------ src/View/renderer.js | 14 --- unit_tests/testRunner.html | 1 + unit_tests/test_constantLayout.js | 92 +++++++------- unit_tests/test_forceBasedLayout.js | 30 +++++ 6 files changed, 201 insertions(+), 151 deletions(-) create mode 100644 unit_tests/test_forceBasedLayout.js diff --git a/src/Layout/constant.js b/src/Layout/constant.js index 74c396b..f64b144 100644 --- a/src/Layout/constant.js +++ b/src/Layout/constant.js @@ -46,6 +46,20 @@ Viva.Graph.Layout.constant = function (graph, userSettings) { graphRect.y2 = Number.MIN_VALUE; graph.forEachNode(ensureNodeInitialized); + }, + + onGraphChanged = function(changes) { + for (var i = 0; i < changes.length; ++i) { + var change = changes[i]; + if (change.changeType === 'add' && change.node) { + ensureNodeInitialized(change.node); + } + } + }, + + initLayout = function () { + updateNodePositions(); + graph.addEventListener('changed', onGraphChanged); }; return { @@ -76,18 +90,12 @@ Viva.Graph.Layout.constant = function (graph, userSettings) { return graphRect; }, - addNode : ensureNodeInitialized, - - removeNode : function (node) { /* nop */ }, - - addLink : function (link) { /* nop */ }, - - removeLink : function (link) { /* nop */ }, - /** * Request to release all resources */ - dispose : function () { /* nop */ }, + dispose : function () { + graph.removeEventListener('change', onGraphChanged); + }, // Layout specific methods: @@ -117,4 +125,4 @@ Viva.Graph.Layout.constant = function (graph, userSettings) { } }; -}; \ No newline at end of file +}; diff --git a/src/Layout/forceDirected.js b/src/Layout/forceDirected.js index 7f8d189..57f74ca 100644 --- a/src/Layout/forceDirected.js +++ b/src/Layout/forceDirected.js @@ -3,13 +3,12 @@ /* jshint camelcase:false */ Viva.Graph.Layout = Viva.Graph.Layout || {}; - -Viva.Graph.Layout.forceDirected = function (graph, settings) { +Viva.Graph.Layout.forceDirected = function(graph, settings) { var STABLE_THRESHOLD = 0.001; // Maximum movement of the system which can be considered as stabilized if (!graph) { throw { - message : "Graph structure cannot be undefined" + message: 'Graph structure cannot be undefined' }; } @@ -17,12 +16,12 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { /** * Ideal length for links (springs in physical model). */ - springLength : 80, + springLength: 80, /** * Hook's law coefficient. 1 - solid spring. */ - springCoeff : 0.0002, + springCoeff: 0.0002, /** * Coulomb's law coefficient. It's used to repel nodes thus should be negative @@ -36,30 +35,31 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { * Setting it to one makes Barnes Hut simulation no different from * brute-force forces calculation (each node is considered). */ - theta : 0.8, + theta: 0.8, /** * Drag force coefficient. Used to slow down system, thus should be less than 1. * The closer it is to 0 the less tight system will be. */ - dragCoeff : 0.02 + dragCoeff: 0.02 }); var forceSimulator = Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()), - - nbodyForce = Viva.Graph.Physics.nbodyForce({gravity : settings.gravity, theta: settings.theta}), - - springForce = Viva.Graph.Physics.springForce({length : settings.springLength, coeff: settings.springCoeff }), - - dragForce = Viva.Graph.Physics.dragForce({coeff: settings.dragCoeff}), - - initializationRequired = true, - + nbodyForce = Viva.Graph.Physics.nbodyForce({ + gravity: settings.gravity, + theta: settings.theta + }), + springForce = Viva.Graph.Physics.springForce({ + length: settings.springLength, + coeff: settings.springCoeff + }), + dragForce = Viva.Graph.Physics.dragForce({ + coeff: settings.dragCoeff + }), graphRect = new Viva.Graph.Rect(), + random = Viva.random('ted.com', 103, 114, 101, 97, 116), - random = Viva.random("ted.com", 103, 114, 101, 97, 116), - - getBestNodePosition = function (node) { + getBestNodePosition = function(node) { // TODO: Initial position could be picked better, e.g. take into // account all neighbouring nodes/links, not only one. // TODO: this is the same as in gem layout. consider refactoring. @@ -77,17 +77,17 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { } return { - x : baseX + random.next(springLength) - springLength / 2, - y : baseY + random.next(springLength) - springLength / 2 + x: baseX + random.next(springLength) - springLength / 2, + y: baseY + random.next(springLength) - springLength / 2 }; }, - updateNodeMass = function (node) { + updateNodeMass = function(node) { var body = node.force_directed_body; body.mass = 1 + graph.getLinks(node.id).length / 3.0; }, - initNode = function (node) { + initNode = function(node) { var body = node.force_directed_body; if (!body) { // TODO: rename position to location or location to position to be consistent with @@ -103,7 +103,7 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { } }, - releaseNode = function (node) { + releaseNode = function(node) { var body = node.force_directed_body; if (body) { node.force_directed_body = null; @@ -113,7 +113,7 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { } }, - initLink = function (link) { + initLink = function(link) { // TODO: what if bodies are not initialized? var from = graph.getNode(link.fromId), to = graph.getNode(link.toId); @@ -123,13 +123,17 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { link.force_directed_spring = forceSimulator.addSpring(from.force_directed_body, to.force_directed_body, -1.0, link.weight); }, - releaseLink = function (link) { + releaseLink = function(link) { var spring = link.force_directed_spring; if (spring) { var from = graph.getNode(link.fromId), to = graph.getNode(link.toId); - if (from) { updateNodeMass(from); } - if (to) { updateNodeMass(to); } + if (from) { + updateNodeMass(from); + } + if (to) { + updateNodeMass(to); + } link.force_directed_spring = null; delete link.force_directed_spring; @@ -138,12 +142,35 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { } }, - initSimulator = function () { + onGraphChanged = function(changes) { + for (var i = 0; i < changes.length; ++i) { + var change = changes[i]; + if (change.changeType === 'add') { + if (change.node) { + initNode(change.node); + } + if (change.link) { + initLink(change.link); + } + } else if (change.changeType === 'remove') { + if (change.node) { + releaseNode(change.node); + } + if (change.link) { + releaseLink(change.link); + } + } + // Probably we don't need to care about 'update' event here; + } + }, + + initSimulator = function() { graph.forEachNode(initNode); graph.forEachLink(initLink); + graph.addEventListener('changed', onGraphChanged); }, - isNodePinned = function (node) { + isNodePinned = function(node) { if (!node) { return true; } @@ -151,17 +178,21 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { return node.isPinned || (node.data && node.data.isPinned); }, - updateNodePositions = function () { + updateNodePositions = function() { var x1 = Number.MAX_VALUE, y1 = Number.MAX_VALUE, x2 = Number.MIN_VALUE, y2 = Number.MIN_VALUE; - if (graph.getNodesCount() === 0) { return; } + if (graph.getNodesCount() === 0) { + return; + } - graph.forEachNode(function (node) { + graph.forEachNode(function(node) { var body = node.force_directed_body; if (!body) { - return; // TODO: maybe we shall initialize it? + // This could be a sign someone removed the propery. + // I should really decouple force related stuff from node + return; } if (isNodePinned(node)) { @@ -172,10 +203,18 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { node.position.x = body.location.x; node.position.y = body.location.y; - if (node.position.x < x1) { x1 = node.position.x; } - if (node.position.x > x2) { x2 = node.position.x; } - if (node.position.y < y1) { y1 = node.position.y; } - if (node.position.y > y2) { y2 = node.position.y; } + if (node.position.x < x1) { + x1 = node.position.x; + } + if (node.position.x > x2) { + x2 = node.position.x; + } + if (node.position.y < y1) { + y1 = node.position.y; + } + if (node.position.y > y2) { + y2 = node.position.y; + } }); graphRect.x1 = x1; @@ -188,13 +227,15 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { forceSimulator.addBodyForce(nbodyForce); forceSimulator.addBodyForce(dragForce); + initSimulator(); + return { /** * Attempts to layout graph within given number of iterations. * * @param {integer} [iterationsCount] number of algorithm's iterations. */ - run : function (iterationsCount) { + run: function(iterationsCount) { var i; iterationsCount = iterationsCount || 50; @@ -203,14 +244,7 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { } }, - step : function () { - // we assume graph was not modified between calls. If it was - // we will have to reinitialize force simulator. - if (initializationRequired) { - initSimulator(); - initializationRequired = false; - } - + step: function() { var energy = forceSimulator.run(20); updateNodePositions(); @@ -221,34 +255,15 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { * Returns rectangle structure {x1, y1, x2, y2}, which represents * current space occupied by graph. */ - getGraphRect : function () { + getGraphRect: function() { return graphRect; }, - addNode : function (node) { - initNode(node); - }, - - removeNode : function (node) { - releaseNode(node); - }, - - addLink : function (link) { - initLink(link); - }, - - removeLink : function (link) { - releaseLink(link); - }, - /** * Request to release all resources */ - dispose : function () { - // Because I do not have reference to all nodes - // they should be disposed externally. Probably this will change - // In future. For now just reset this flag. - initializationRequired = true; + dispose: function() { + graph.removeEventListener('change', onGraphChanged); }, // Layout specific methods @@ -258,24 +273,28 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { * @param length new desired length of the springs (aka edge, aka link). * if this parameter is empty then old spring length is returned. */ - springLength : function (length) { + springLength: function(length) { if (arguments.length === 1) { - springForce.options({ length : length }); + springForce.options({ + length: length + }); return this; } return springForce.options().length; }, - /** + /** * Gets or sets current spring coeffiсient. * * @param coeff new spring coeffiсient. * if this parameter is empty then its old value returned. */ - springCoeff : function (coeff) { + springCoeff: function(coeff) { if (arguments.length === 1) { - springForce.options({ coeff : coeff }); + springForce.options({ + coeff: coeff + }); return this; } @@ -288,9 +307,11 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { * @param g new gravity constant. * if this parameter is empty then its old value returned. */ - gravity : function (g) { + gravity: function(g) { if (arguments.length === 1) { - nbodyForce.options({ gravity : g }); + nbodyForce.options({ + gravity: g + }); return this; } @@ -303,9 +324,11 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { * @param t new theta coeffiсient. * if this parameter is empty then its old value returned. */ - theta : function (t) { + theta: function(t) { if (arguments.length === 1) { - nbodyForce.options({ theta : t }); + nbodyForce.options({ + theta: t + }); return this; } @@ -318,13 +341,15 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { * @param dragCoeff new drag coeffiсient. * if this parameter is empty then its old value returned. */ - drag : function (dragCoeff) { + drag: function(dragCoeff) { if (arguments.length === 1) { - dragForce.options({ coeff : dragCoeff }); + dragForce.options({ + coeff: dragCoeff + }); return this; } return dragForce.options().coeff; } }; -}; \ No newline at end of file +}; diff --git a/src/View/renderer.js b/src/View/renderer.js index 68926f8..8573447 100644 --- a/src/View/renderer.js +++ b/src/View/renderer.js @@ -28,7 +28,6 @@ Viva.Graph.View = Viva.Graph.View || {}; * // Layout algorithm to be used. The algorithm is expected to comply with defined * // interface and is expected to be iterative. Renderer will use it then to calculate * // grpaph's layout. For examples of the interface refer to Viva.Graph.Layout.forceDirected() - * // and Viva.Graph.Layout.gem() algorithms. * layout : Viva.Graph.Layout.forceDirected(), * * // Directs renderer to display links. Usually rendering links is the slowest part of this @@ -169,8 +168,6 @@ Viva.Graph.View.renderer = function (graph, settings) { for (i = 0; i < settings.prerender; i += 1) { layout.step(); } - } else { - layout.step(); // make one step to init positions property. } }, @@ -190,7 +187,6 @@ Viva.Graph.View.renderer = function (graph, settings) { var nodeUI = graphics.node(node); node.ui = nodeUI; graphics.initNode(nodeUI); - layout.addNode(node); renderNode(node); }, @@ -202,8 +198,6 @@ Viva.Graph.View.renderer = function (graph, settings) { node.ui = null; delete node.ui; } - - layout.removeNode(node); }, createLinkUi = function (link) { @@ -297,16 +291,9 @@ Viva.Graph.View.renderer = function (graph, settings) { var link = change.link; if (change.changeType === 'add') { if (settings.renderLinks) { createLinkUi(link); } - layout.addLink(link); } else if (change.changeType === 'remove') { if (settings.renderLinks) { removeLinkUi(link); } - layout.removeLink(link); } else if (change.changeType === 'update') { - // if (settings.renderLinks) { removeLinkUi(link); } - // layout.removeLink(link); - - // if (settings.renderLinks) { createLinkUi(link); } - // layout.addLink(link); throw 'Update type is not implemented. TODO: Implement me!'; } }, @@ -383,7 +370,6 @@ Viva.Graph.View.renderer = function (graph, settings) { graph.forEachLink(function (link) { if (settings.renderLinks) { removeLinkUi(link); } - layout.removeLink(link); }); graph.forEachNode(function (node) { diff --git a/unit_tests/testRunner.html b/unit_tests/testRunner.html index f68316a..e40a6aa 100644 --- a/unit_tests/testRunner.html +++ b/unit_tests/testRunner.html @@ -12,6 +12,7 @@ + + + + + +
+ + diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 28e783d..358b4fb 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -2226,13 +2226,12 @@ Viva.Graph.Physics.forceSimulator = function (forceIntegrator) { /* jshint camelcase:false */ Viva.Graph.Layout = Viva.Graph.Layout || {}; - -Viva.Graph.Layout.forceDirected = function (graph, settings) { +Viva.Graph.Layout.forceDirected = function(graph, settings) { var STABLE_THRESHOLD = 0.001; // Maximum movement of the system which can be considered as stabilized if (!graph) { throw { - message : "Graph structure cannot be undefined" + message: 'Graph structure cannot be undefined' }; } @@ -2240,12 +2239,12 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { /** * Ideal length for links (springs in physical model). */ - springLength : 80, + springLength: 80, /** * Hook's law coefficient. 1 - solid spring. */ - springCoeff : 0.0002, + springCoeff: 0.0002, /** * Coulomb's law coefficient. It's used to repel nodes thus should be negative @@ -2259,30 +2258,31 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { * Setting it to one makes Barnes Hut simulation no different from * brute-force forces calculation (each node is considered). */ - theta : 0.8, + theta: 0.8, /** * Drag force coefficient. Used to slow down system, thus should be less than 1. * The closer it is to 0 the less tight system will be. */ - dragCoeff : 0.02 + dragCoeff: 0.02 }); var forceSimulator = Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()), - - nbodyForce = Viva.Graph.Physics.nbodyForce({gravity : settings.gravity, theta: settings.theta}), - - springForce = Viva.Graph.Physics.springForce({length : settings.springLength, coeff: settings.springCoeff }), - - dragForce = Viva.Graph.Physics.dragForce({coeff: settings.dragCoeff}), - - initializationRequired = true, - + nbodyForce = Viva.Graph.Physics.nbodyForce({ + gravity: settings.gravity, + theta: settings.theta + }), + springForce = Viva.Graph.Physics.springForce({ + length: settings.springLength, + coeff: settings.springCoeff + }), + dragForce = Viva.Graph.Physics.dragForce({ + coeff: settings.dragCoeff + }), graphRect = new Viva.Graph.Rect(), + random = Viva.random('ted.com', 103, 114, 101, 97, 116), - random = Viva.random("ted.com", 103, 114, 101, 97, 116), - - getBestNodePosition = function (node) { + getBestNodePosition = function(node) { // TODO: Initial position could be picked better, e.g. take into // account all neighbouring nodes/links, not only one. // TODO: this is the same as in gem layout. consider refactoring. @@ -2300,17 +2300,17 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { } return { - x : baseX + random.next(springLength) - springLength / 2, - y : baseY + random.next(springLength) - springLength / 2 + x: baseX + random.next(springLength) - springLength / 2, + y: baseY + random.next(springLength) - springLength / 2 }; }, - updateNodeMass = function (node) { + updateNodeMass = function(node) { var body = node.force_directed_body; body.mass = 1 + graph.getLinks(node.id).length / 3.0; }, - initNode = function (node) { + initNode = function(node) { var body = node.force_directed_body; if (!body) { // TODO: rename position to location or location to position to be consistent with @@ -2326,7 +2326,7 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { } }, - releaseNode = function (node) { + releaseNode = function(node) { var body = node.force_directed_body; if (body) { node.force_directed_body = null; @@ -2336,7 +2336,7 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { } }, - initLink = function (link) { + initLink = function(link) { // TODO: what if bodies are not initialized? var from = graph.getNode(link.fromId), to = graph.getNode(link.toId); @@ -2346,13 +2346,17 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { link.force_directed_spring = forceSimulator.addSpring(from.force_directed_body, to.force_directed_body, -1.0, link.weight); }, - releaseLink = function (link) { + releaseLink = function(link) { var spring = link.force_directed_spring; if (spring) { var from = graph.getNode(link.fromId), to = graph.getNode(link.toId); - if (from) { updateNodeMass(from); } - if (to) { updateNodeMass(to); } + if (from) { + updateNodeMass(from); + } + if (to) { + updateNodeMass(to); + } link.force_directed_spring = null; delete link.force_directed_spring; @@ -2361,12 +2365,35 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { } }, - initSimulator = function () { + onGraphChanged = function(changes) { + for (var i = 0; i < changes.length; ++i) { + var change = changes[i]; + if (change.changeType === 'add') { + if (change.node) { + initNode(change.node); + } + if (change.link) { + initLink(change.link); + } + } else if (change.changeType === 'remove') { + if (change.node) { + releaseNode(change.node); + } + if (change.link) { + releaseLink(change.link); + } + } + // Probably we don't need to care about 'update' event here; + } + }, + + initSimulator = function() { graph.forEachNode(initNode); graph.forEachLink(initLink); + graph.addEventListener('changed', onGraphChanged); }, - isNodePinned = function (node) { + isNodePinned = function(node) { if (!node) { return true; } @@ -2374,17 +2401,21 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { return node.isPinned || (node.data && node.data.isPinned); }, - updateNodePositions = function () { + updateNodePositions = function() { var x1 = Number.MAX_VALUE, y1 = Number.MAX_VALUE, x2 = Number.MIN_VALUE, y2 = Number.MIN_VALUE; - if (graph.getNodesCount() === 0) { return; } + if (graph.getNodesCount() === 0) { + return; + } - graph.forEachNode(function (node) { + graph.forEachNode(function(node) { var body = node.force_directed_body; if (!body) { - return; // TODO: maybe we shall initialize it? + // This could be a sign someone removed the propery. + // I should really decouple force related stuff from node + return; } if (isNodePinned(node)) { @@ -2395,10 +2426,18 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { node.position.x = body.location.x; node.position.y = body.location.y; - if (node.position.x < x1) { x1 = node.position.x; } - if (node.position.x > x2) { x2 = node.position.x; } - if (node.position.y < y1) { y1 = node.position.y; } - if (node.position.y > y2) { y2 = node.position.y; } + if (node.position.x < x1) { + x1 = node.position.x; + } + if (node.position.x > x2) { + x2 = node.position.x; + } + if (node.position.y < y1) { + y1 = node.position.y; + } + if (node.position.y > y2) { + y2 = node.position.y; + } }); graphRect.x1 = x1; @@ -2411,13 +2450,15 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { forceSimulator.addBodyForce(nbodyForce); forceSimulator.addBodyForce(dragForce); + initSimulator(); + return { /** * Attempts to layout graph within given number of iterations. * * @param {integer} [iterationsCount] number of algorithm's iterations. */ - run : function (iterationsCount) { + run: function(iterationsCount) { var i; iterationsCount = iterationsCount || 50; @@ -2426,14 +2467,7 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { } }, - step : function () { - // we assume graph was not modified between calls. If it was - // we will have to reinitialize force simulator. - if (initializationRequired) { - initSimulator(); - initializationRequired = false; - } - + step: function() { var energy = forceSimulator.run(20); updateNodePositions(); @@ -2444,34 +2478,15 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { * Returns rectangle structure {x1, y1, x2, y2}, which represents * current space occupied by graph. */ - getGraphRect : function () { + getGraphRect: function() { return graphRect; }, - addNode : function (node) { - initNode(node); - }, - - removeNode : function (node) { - releaseNode(node); - }, - - addLink : function (link) { - initLink(link); - }, - - removeLink : function (link) { - releaseLink(link); - }, - /** * Request to release all resources */ - dispose : function () { - // Because I do not have reference to all nodes - // they should be disposed externally. Probably this will change - // In future. For now just reset this flag. - initializationRequired = true; + dispose: function() { + graph.removeEventListener('change', onGraphChanged); }, // Layout specific methods @@ -2481,24 +2496,28 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { * @param length new desired length of the springs (aka edge, aka link). * if this parameter is empty then old spring length is returned. */ - springLength : function (length) { + springLength: function(length) { if (arguments.length === 1) { - springForce.options({ length : length }); + springForce.options({ + length: length + }); return this; } return springForce.options().length; }, - /** + /** * Gets or sets current spring coeffiсient. * * @param coeff new spring coeffiсient. * if this parameter is empty then its old value returned. */ - springCoeff : function (coeff) { + springCoeff: function(coeff) { if (arguments.length === 1) { - springForce.options({ coeff : coeff }); + springForce.options({ + coeff: coeff + }); return this; } @@ -2511,9 +2530,11 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { * @param g new gravity constant. * if this parameter is empty then its old value returned. */ - gravity : function (g) { + gravity: function(g) { if (arguments.length === 1) { - nbodyForce.options({ gravity : g }); + nbodyForce.options({ + gravity: g + }); return this; } @@ -2526,9 +2547,11 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { * @param t new theta coeffiсient. * if this parameter is empty then its old value returned. */ - theta : function (t) { + theta: function(t) { if (arguments.length === 1) { - nbodyForce.options({ theta : t }); + nbodyForce.options({ + theta: t + }); return this; } @@ -2541,16 +2564,19 @@ Viva.Graph.Layout.forceDirected = function (graph, settings) { * @param dragCoeff new drag coeffiсient. * if this parameter is empty then its old value returned. */ - drag : function (dragCoeff) { + drag: function(dragCoeff) { if (arguments.length === 1) { - dragForce.options({ coeff : dragCoeff }); + dragForce.options({ + coeff: dragCoeff + }); return this; } return dragForce.options().coeff; } }; -};Viva.Graph.Layout = Viva.Graph.Layout || {}; +}; +Viva.Graph.Layout = Viva.Graph.Layout || {}; /** * Does not really perform any layouting algorithm but is compliant @@ -2598,6 +2624,20 @@ Viva.Graph.Layout.constant = function (graph, userSettings) { graphRect.y2 = Number.MIN_VALUE; graph.forEachNode(ensureNodeInitialized); + }, + + onGraphChanged = function(changes) { + for (var i = 0; i < changes.length; ++i) { + var change = changes[i]; + if (change.changeType === 'add' && change.node) { + ensureNodeInitialized(change.node); + } + } + }, + + initLayout = function () { + updateNodePositions(); + graph.addEventListener('changed', onGraphChanged); }; return { @@ -2628,18 +2668,12 @@ Viva.Graph.Layout.constant = function (graph, userSettings) { return graphRect; }, - addNode : ensureNodeInitialized, - - removeNode : function (node) { /* nop */ }, - - addLink : function (link) { /* nop */ }, - - removeLink : function (link) { /* nop */ }, - /** * Request to release all resources */ - dispose : function () { /* nop */ }, + dispose : function () { + graph.removeEventListener('change', onGraphChanged); + }, // Layout specific methods: @@ -2669,7 +2703,8 @@ Viva.Graph.Layout.constant = function (graph, userSettings) { } }; -};/** +}; +/** * @fileOverview Defines a graph renderer that uses CSS based drawings. * * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com @@ -2699,7 +2734,6 @@ Viva.Graph.View = Viva.Graph.View || {}; * // Layout algorithm to be used. The algorithm is expected to comply with defined * // interface and is expected to be iterative. Renderer will use it then to calculate * // grpaph's layout. For examples of the interface refer to Viva.Graph.Layout.forceDirected() - * // and Viva.Graph.Layout.gem() algorithms. * layout : Viva.Graph.Layout.forceDirected(), * * // Directs renderer to display links. Usually rendering links is the slowest part of this @@ -2840,8 +2874,6 @@ Viva.Graph.View.renderer = function (graph, settings) { for (i = 0; i < settings.prerender; i += 1) { layout.step(); } - } else { - layout.step(); // make one step to init positions property. } }, @@ -2861,7 +2893,6 @@ Viva.Graph.View.renderer = function (graph, settings) { var nodeUI = graphics.node(node); node.ui = nodeUI; graphics.initNode(nodeUI); - layout.addNode(node); renderNode(node); }, @@ -2873,8 +2904,6 @@ Viva.Graph.View.renderer = function (graph, settings) { node.ui = null; delete node.ui; } - - layout.removeNode(node); }, createLinkUi = function (link) { @@ -2954,13 +2983,11 @@ Viva.Graph.View.renderer = function (graph, settings) { updateCenterRequired = true; // Next time when node is added - center the graph. } } else if (change.changeType === 'update') { + releaseNodeEvents(node); + removeNodeUi(node); - // releaseNodeEvents(node); - // removeNodeUi(node); - - // createNodeUi(node); - // listenNodeEvents(node); - throw 'Update type is not implemented. TODO: Implement me!'; + createNodeUi(node); + listenNodeEvents(node); } }, @@ -2968,16 +2995,9 @@ Viva.Graph.View.renderer = function (graph, settings) { var link = change.link; if (change.changeType === 'add') { if (settings.renderLinks) { createLinkUi(link); } - layout.addLink(link); } else if (change.changeType === 'remove') { if (settings.renderLinks) { removeLinkUi(link); } - layout.removeLink(link); } else if (change.changeType === 'update') { - // if (settings.renderLinks) { removeLinkUi(link); } - // layout.removeLink(link); - - // if (settings.renderLinks) { createLinkUi(link); } - // layout.addLink(link); throw 'Update type is not implemented. TODO: Implement me!'; } }, @@ -3054,7 +3074,6 @@ Viva.Graph.View.renderer = function (graph, settings) { graph.forEachLink(function (link) { if (settings.renderLinks) { removeLinkUi(link); } - layout.removeLink(link); }); graph.forEachNode(function (node) { diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index f58034d..2779a6b 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.4.0",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){function e(){var e=4022871197,t=function(t){var n;for(t=""+t,n=0;t.length>n;n++){e+=t.charCodeAt(n);var r=.02519603282416938*e;e=r>>>0,r-=e,r*=e,e=r>>>0,r-=e,e+=4294967296*r}return 2.3283064365386963e-10*(e>>>0)};return t.version="Mash 0.9",t}function t(t){return function(t){var n,r,i=0,o=58,a=119,u=178,s=[],f=e();for(0===t.length&&(t=[+new Date]),n=0;256>n;n++)s[n]=f(" "),s[n]-=4.76837158203125e-7*f(" "),0>s[n]&&(s[n]+=1);for(r=0;t.length>r;r++)for(n=0;256>n;n++)s[n]-=f(t[r]),s[n]-=4.76837158203125e-7*f(t[r]),0>s[n]&&(s[n]+=1);f=null;var c=function(){var e;return i=255&i+1,o=255&o+1,a=255&a+1,u=255&u+1,e=s[i]-s[o],0>e&&(e+=1),e-=s[a],0>e&&(e+=1),e-=s[u],0>e&&(e+=1),s[i]=e,e};return c.uint32=function(){return 4294967296*c()>>>0},c.fract53=c,c.version="LFIB4 0.9",c.args=t,c}(t)}var n=new t(Array.prototype.slice.call(arguments));return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,l=0,d=0,h=!1,p=0,v=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-l,y:r-d}),l=t,d=r},y=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},g=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return y(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return y(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(l=e.clientX,d=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:l,y:d}),s.on("mousemove",w),s.on("mouseup",b),y(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},E=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=v(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},G=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",E,!1):e.addEventListener("DOMMouseScroll",E,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",E,!1):e.removeEventListener("DOMMouseScroll",E,!1)),i=t},N=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},P=function(e){if(1===e.touches.length){y(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=N(e.touches[0],e.touches[1]),r=0;p>n?r=-1:n>p&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),p=n,y(e),g(e)}},_=function(e){h=!1,s.stop("touchmove",P),s.stop("touchend",_),s.stop("touchcancel",_),u=null,r&&r(e)},L=function(e,n){y(e),g(e),l=n.clientX,d=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:l,y:d}),h||(h=!0,s.on("touchmove",P),s.on("touchend",_),s.on("touchcancel",_))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?L(t,t.touches[0]):(2===t.touches.length&&(y(t),g(t),p=N(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return G(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",P),s.stop("touchend",_),s.stop("touchcancel",_),G(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(){return{bindDragNDrop:function(e,t){if(t){var n=Viva.Graph.Utils.dragndrop(e.ui);"function"==typeof t.onStart&&n.onStart(t.onStart),"function"==typeof t.onDrag&&n.onDrag(t.onDrag),"function"==typeof t.onStop&&n.onStop(t.onStop),e.events=n}else e.events&&(e.events.release(),e.events=null,delete e.events)}}},Viva.Graph.spatialIndex=function(e,t){var n,r,i=16;return"function"==typeof t?(r=t,n=function(t,n){var i=null;return e.forEachNode(function(e){return r(e,t,n)?(i=e,!0):void 0}),i}):"number"==typeof t&&(i=t,n=function(t,n){var r=null;return e.forEachNode(function(e){var o=e.position;return t>o.x-i&&o.x+i>t&&n>o.y-i&&o.y+i>n?(r=e,!0):void 0}),r}),{getNodeAt:n}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,l,d,h,p,v,m,y,g,x,w,V={x:0,y:0};return s=r-t,c=e-n,d=n*t-e*r,m=s*i+c*o+d,y=s*a+c*u+d,0!==m&&0!==y&&m>=0==y>=4?null:(f=u-o,l=i-a,h=a*o-i*u,p=f*e+l*t+h,v=f*n+l*r+h,0!==p&&0!==v&&p>=0==v>=0?null:(g=s*l-f*c,0===g?null:(x=0>g?-g/2:g/2,x=0,w=c*h-l*d,V.x=(0>w?w-x:w+x)/g,w=f*d-s*h,V.y=(0>w?w-x:w+x)/g,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var l=i(a);l===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=l}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n){this.fromId=e,this.toId=t,this.data=n},Viva.Graph.graph=function(){var e={},t=[],n=0,r=0,i=[],o=function(e){e.fire("changed",i)},a=function(){r+=1},u=function(e){r-=1,0===r&&i.length>0&&(o(e),i.length=0)},s=function(e,t){i.push({node:e,changeType:t})},f=function(e,t){i.push({link:e,changeType:t})},c=function(e){return e&&"object"==typeof e&&"number"==typeof e.length&&"function"==typeof e.splice&&!e.propertyIsEnumerable("length")},l={addNode:function(t,r){if(t===void 0)throw{message:"Invalid node identifier"};a();var i=this.getNode(t);if(i?s(i,"update"):(i=new Viva.Graph.Node(t),n++,s(i,"add")),r){var o,f=i.data||{},l=typeof r;if("string"===l||c(r)||"number"===l||"boolean"===l)f=r;else if("undefined"===l)f=null;else for(o in r)r.hasOwnProperty(o)&&(f[o]=r[o]);i.data=f}return e[t]=i,u(this),i},addLink:function(e,n,r){a();var i=this.getNode(e)||this.addNode(e),o=this.getNode(n)||this.addNode(n),s=new Viva.Graph.Link(e,n,r);return t.push(s),i.links.push(s),o.links.push(s),f(s,"add"),u(this),s},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;a(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),f(e,"remove"),u(this),!0},removeNode:function(t){var r=this.getNode(t);if(!r)return!1;for(a();r.links.length;){var i=r.links[0];this.removeLink(i)}e[t]=null,delete e[t],n--,s(r,"remove"),u(this)},getNode:function(t){return e[t]},getNodesCount:function(){return n},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n;if("function"==typeof e)for(n=0;t.length>n;++n)e(t[n])},beginUpdate:function(){a()},endUpdate:function(){u(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(l).extend(),l},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,l=Math.sqrt(f*f+c*c);l>r&&(u.velocity.x=r*f/l,u.velocity.y=r*c/l),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,l=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},d=l(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return.01>n&&.01>r},p=function(e){for(o.reset(),o.push(d,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,p=n.top,v=(n.bottom+p)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>v){s+=2;var y=p;p=v,v+=v-y}var g=n.quads[s];g||(g=l(),g.left=f,g.top=p,g.right=c,g.bottom=v,n.quads[s]=g),o.push(g,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){var w,V;do{var b=2*u.nextDouble()*Math.PI,E=.006*(n.right-n.left)*Math.cos(b),G=.006*(n.bottom-n.top)*Math.sin(b);w=x.location.x+E,V=x.location.y+G}while(n.left>w||w>n.right||n.top>V||V>n.bottom);x.location.x=w,x.location.y=V}o.push(n,x),o.push(n,r)}else n.body=r}},v=function(e){var t,n,o,s,f=i,c=1,l=0,h=1;for(f[0]=d;c;){var p=f[l],v=p.body;c-=1,l+=1,v&&v!==e?(n=v.location.x-e.location.x,o=v.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=p.massX/p.mass-e.location.x,o=p.massY/p.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(p.right-p.left)/s?(t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(p.quads[0]&&(f[h]=p.quads[0],c+=1,h+=1),p.quads[1]&&(f[h]=p.quads[1],c+=1,h+=1),p.quads[2]&&(f[h]=p.quads[2],c+=1,h+=1),p.quads[3]&&(f[h]=p.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,v=o-r;for(h>v?o=r+h:i=n+v,c=0,d=l(),d.left=n,d.right=i,d.top=r,d.bottom=o,t=u;t--;)p(a[t],d)};return{insert:p,init:m,update:v,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{init:function(){},update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{init:function(){},update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t=e,n=[],r=[],i=[],o=[];return{speedLimit:1,bodies:n,accumulate:function(){var e,t,a;for(e=i.length;e--;)i[e].init(this);for(e=o.length;e--;)o[e].init(this);for(e=n.length;e--;)for(a=n[e],a.force.x=0,a.force.y=0,t=0;i.length>t;t++)i[t].update(a);for(e=0;r.length>e;++e)for(t=0;o.length>t;t++)o[t].update(r[e])},run:function(e){return this.accumulate(),t.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return n.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,n);return 0>t?!1:n.splice(t,1)},addSpring:function(e,t,n,i,o){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};o="number"==typeof o?o:1;var a=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,o);return r.push(a),a},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,r);return 0>t?!1:r.splice(t,1)},addBodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};i.push(e)},addSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};o.push(e)}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=!0,s=new Viva.Graph.Rect,f=Viva.random("ted.com",103,114,101,97,116),c=function(n){var r=(s.x1+s.x2)/2,i=(s.y1+s.y2)/2,o=t.springLength;if(n.links&&n.links.length>0){var a=n.links[0],u=a.fromId!==n.id?e.getNode(a.fromId):e.getNode(a.toId);u.position&&(r=u.position.x,i=u.position.y)}return{x:r+f.next(o)-o/2,y:i+f.next(o)-o/2}},l=function(t){var n=t.force_directed_body;n.mass=1+e.getLinks(t.id).length/3},d=function(e){var t=e.force_directed_body;t||(e.position=e.position||c(e),t=new Viva.Graph.Physics.Body,e.force_directed_body=t,l(e),t.loc(e.position),r.addBody(t))},h=function(e){var t=e.force_directed_body;t&&(e.force_directed_body=null,delete e.force_directed_body,r.removeBody(t))},p=function(t){var n=e.getNode(t.fromId),i=e.getNode(t.toId);l(n),l(i),t.force_directed_spring=r.addSpring(n.force_directed_body,i.force_directed_body,-1,t.weight)},v=function(t){var n=t.force_directed_spring;if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&l(i),o&&l(o),t.force_directed_spring=null,delete t.force_directed_spring,r.removeSpring(n)}},m=function(){e.forEachNode(d),e.forEachLink(p)},y=function(e){return e?e.isPinned||e.data&&e.data.isPinned:!0},g=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;0!==e.getNodesCount()&&(e.forEachNode(function(e){var o=e.force_directed_body;o&&(y(e)&&o.loc(e.position),e.position.x=o.location.x,e.position.y=o.location.y,t>e.position.x&&(t=e.position.x),e.position.x>r&&(r=e.position.x),n>e.position.y&&(n=e.position.y),e.position.y>i&&(i=e.position.y))}),s.x1=t,s.x2=r,s.y1=n,s.y2=i)};return r.addSpringForce(o),r.addBodyForce(i),r.addBodyForce(a),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){u&&(m(),u=!1);var e=r.run(20);return g(),n>e},getGraphRect:function(){return s},addNode:function(e){d(e)},removeNode:function(e){h(e)},addLink:function(e){p(e)},removeLink:function(e){v(e)},dispose:function(){u=!0},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.position.xt.x2&&(t.x2=e.position.x),e.position.yt.y2&&(t.y2=e.position.y)},a=function(e){e.hasOwnProperty("position")||(e.position=i(e)),o(e,r)},u=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(a))};return{run:function(){this.step()},step:function(){return u(),!1},getGraphRect:function(){return r},addNode:a,removeNode:function(){},addLink:function(){},removeLink:function(){},dispose:function(){},placeNode:function(e){return"function"==typeof e?(i=e,u(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,l=!0,d=0,h=0,p=!1,v=!1,m={x:0,y:0},y={offsetX:0,offsetY:0,scale:1},g=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x={x:0,y:0,node:null},w={x:0,y:0,node:null},V={x:0,y:0},b=Viva.Graph.Utils.events(window),E=Viva.Graph.Utils.events({}).extend(),G=function(t){var n=e.getNode(t.fromId),r=e.getNode(t.toId);n&&r&&(x.x=n.position.x,x.y=n.position.y,x.node=n,w.x=r.position.x,w.y=r.position.y,w.node=r,s.updateLinkPosition(t.ui,x,w))},N=function(e){V.x=e.position.x,V.y=e.position.y,s.updateNodePosition(e.ui,V)},P=function(){s.beginRender(),t.renderLinks&&!s.omitLinksRendering&&e.forEachLink(G),e.forEachNode(N),s.endRender()},_=function(){return p=u.step()&&!v,P(),!p},L=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return _()},n)):(d=0,h=0,i=Viva.Graph.Utils.timer(_,n)),void 0)},A=function(){p=!1,i.restart()},I=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step();else u.step()},k=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,y.offsetX=t.width/2-(e.x2+e.x1)/2,y.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(y.offsetX+m.x,y.offsetY+m.y),l=!1},C=function(e){var t=s.node(e);e.ui=t,s.initNode(t),u.addNode(e),N(e)},T=function(e){e.hasOwnProperty("ui")&&(s.releaseNode(e.ui),e.ui=null,delete e.ui),u.removeNode(e)},M=function(e){var t=s.link(e);e.ui=t,s.initLink(t),s.omitLinksRendering||G(e)},S=function(e){e.hasOwnProperty("ui")&&(s.releaseLink(e.ui),e.ui=null,delete e.ui)},U=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=e.isPinned,e.isPinned=!0,v=!0,A()},onDrag:function(t,n){e.position.x+=n.x/y.scale,e.position.y+=n.y/y.scale,v=!0,P()},onStop:function(){e.isPinned=t,v=!1}})},R=function(e){r.bindDragNDrop(e,null)},D=function(){s.init(f),e.forEachNode(C),t.renderLinks&&e.forEachLink(M)},F=function(){s.release(f)},O=function(t){var n=t.node;if("add"===t.changeType)C(n),U(n),l&&k();else if("remove"===t.changeType)R(n),T(n),0===e.getNodesCount()&&(l=!0);else if("update"===t.changeType)throw"Update type is not implemented. TODO: Implement me!"},z=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&M(n),u.addLink(n);else if("remove"===e.changeType)t.renderLinks&&S(n),u.removeLink(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},B=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?O(n):n.link&&z(n);A()},Y=function(){k(),_()},X=function(){a&&(a.release(),a=null)},q=function(){o&&(o.stop("changed",B),o=null)},W=function(){b.on("resize",Y),X(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),P()}),a.onScroll(function(e,t,n){var r=Math.pow(1.4,0>t?-.2:.2);y.scale=s.scale(r,n),P(),E.fire("scale",y.scale)}),e.forEachNode(U),q(),o=Viva.Graph.Utils.events(e),o.on("changed",B)},j=function(){c=!1,q(),X(),b.stop("resize",Y),E.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&S(e),u.removeLink(e)}),e.forEachNode(function(e){R(e),T(e)}),u.dispose(),F()};return{run:function(e){return c||(g(),I(),k(),D(),W(),c=!0),L(e),this},reset:function(){s.resetScale(),k(),y.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return P(),this},dispose:function(){j()},on:function(e,t){return E.addEventListener(e,t),this},off:function(e,t){return E.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],l=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,l,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r); -return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},l=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},d=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?l(e):(l=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,d()},translateRel:function(e,r){t+=e,n+=r,d()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,d()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),l=f.attr("id"),d=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&l===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&d===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i=1,o=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},a=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},u=function(){return Viva.Graph.svg("line").attr("stroke","#999")},s=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},f=function(e){e.fire("rescaled")},c=function(){if(e){var t="matrix("+i+", 0, 0,"+i+","+n+","+r+")";e.attr("transform",t)}},l={node:function(e){return e&&"function"!=typeof e?o(e):(o=e,this)},link:function(e){return e&&"function"!=typeof e?u(e):(u=e,this)},placeNode:function(e){return a=e,this},placeLink:function(e){return s=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,c()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(o,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(o).translate(-u.x,-u.y),c=e.getCTM().multiply(s);i=c.a,n=c.e,r=c.f;var l="matrix("+c.a+", 0, 0,"+c.d+","+c.e+","+c.f+")";return e.attr("transform",l),f(this),i},resetScale:function(){i=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),f(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),c()},release:function(e){t&&e&&e.removeChild(t)},initLink:function(t){t&&(e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t))},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){a(e,t)},updateLinkPosition:function(e,t,n){s(e,t,n)},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(l).extend(),l},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,l=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(l.x)+" "+Math.round(l.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),d=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),p=new Float32Array(h),v=new Uint32Array(h),m=0,y=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(v),p=t,v=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(d,l),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;p[n*f]=t.x,p[n*f+1]=t.y,p[n*f+2]=e.size,v[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(v,e.id*f,m*f,f)},createNode:function(){y(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),p=0,v=new ArrayBuffer(16*l),m=new Float32Array(v),y=new Uint32Array(v),g=function(){if((p+1)*l>v.byteLength){var e=new ArrayBuffer(2*v.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(y),m=t,y=n,v=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,d),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,y[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,y[i+5]=e.color},createLink:function(e){g(),p+=1,o=e.id},removeLink:function(e){p>0&&(p-=1),p>e.id&&p>0&&r.copyArrayPart(y,e.id*c,p*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,v,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*p),o=p-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},l=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},d=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},p=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},v=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=d(e),o={offset:e};r.textureNumber>=s.length&&l();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=d(t.offset),r=d(o);v(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],p(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){p(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,l=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),d=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,p=0,v=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},y=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(d,l),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;v[n]=t.x-e.size,v[n+1]=t.y-e.size,v[n+2]=4*e._offset,v[n+3]=t.x+e.size,v[n+4]=t.y-e.size,v[n+5]=4*e._offset+1,v[n+6]=t.x-e.size,v[n+7]=t.y+e.size,v[n+8]=4*e._offset+2,v[n+9]=t.x-e.size,v[n+10]=t.y+e.size,v[n+11]=4*e._offset+2,v[n+12]=t.x+e.size,v[n+13]=t.y-e.size,v[n+14]=4*e._offset+1,v[n+15]=t.x+e.size,v[n+16]=t.y+e.size,v[n+17]=4*e._offset+3},createNode:function(t){v=i.extendArray(v,p,c),p+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){p>0&&(p-=1),p>t.id&&p>0&&(t.src&&e.remove(t.src),i.copyArrayPart(v,t.id*c,p*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,v,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),y(),n.drawArrays(n.TRIANGLES,0,6*p)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f,c=0,l=0,d=[],h=[],p=Viva.Graph.View.webglLinkProgram(),v=Viva.Graph.View.webglNodeProgram(),m=function(){return Viva.Graph.View.webglSquare()},y=function(){return Viva.Graph.View.webglLine(3014898687)},g=function(){p.updateTransform(a),v.updateTransform(a)},x=function(){a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},w=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),p&&p.updateSize(i/2,o/2),v&&v.updateSize(i/2,o/2))},V=function(e){var t=c++,n=m(e);return n.id=t,v.createNode(n),d[t]=e,n},b=function(e){var t=l++,n=y(e);return n.id=t,p.createLink(n),h[t]=e,n},E=function(e){e.fire("rescaled")},G={node:function(e){return e&&"function"!=typeof e?V(e):(m=e,this)},link:function(e){return e&&"function"!=typeof e?b(e):(y=e,this)},placeNode:function(e){return u=e,this},placeLink:function(e){return s=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){l>0&&p.render(),c>0&&v.render()},bringLinkToFront:function(e){var t,n,r=p.getFrontLinkId();p.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].ui.id=r,h[t]=n,h[t].ui.id=t)},graphCenterChanged:function(){w()},initLink:function(){},initNode:function(){},translateRel:function(e,t){a[12]+=2*a[0]*e/i/a[0],a[13]-=2*a[5]*t/o/a[5],g()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=a[12],r-=a[13],a[12]+=n*(1-e),a[13]+=r*(1-e),a[0]*=e,a[5]*=e,g(),E(this),a[0]},resetScale:function(){return x(),r&&(w(),g()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),w(),x(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var s="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(s),s}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}p.load(r),p.updateSize(i/2,o/2),v.load(r),v.updateSize(i/2,o/2),g(),"function"==typeof f&&f(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){l>0&&(l-=1),p.removeLink(e);var t=e.id;if(l>t){if(0===l||l===t)return;h[t]=h[l],h[t].ui.id=t}},releaseNode:function(e){if(c>0&&(c-=1),v.removeNode(e),c>e.id){var t=e.id;if(0===c||c===t)return;var n=d[c],r=d[t];d[t]=n,d[t].ui.id=t,v.replaceProperties(r.ui,n.ui)}},updateNodePosition:function(e,t){t.y=-t.y,u&&u(e,t),v.position(e,t)},updateLinkPosition:function(e,t,n){t.y=-t.y,n.y=-n.y,s&&s(e,t,n),p.position(e,t,n)},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):f=e),n},setNodeProgram:function(e){if(!r&&e)v=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)p=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},getGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-a[12])/a[0],e.y=(e.y-a[13])/a[5],e.x*=i/2,e.y*=-o/2,e}};return Viva.Graph.Utils.events(G).extend(),G},Viva.Graph.webglInputEvents=function(e,t){if(e.webglInputEvents)return e.webglInputEvents;var n,r,i=function(e,t,n){if(e.ui&&e.ui.size){var r=e.position,i=e.ui.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},o=null,a=Viva.Graph.spatialIndex(t,i),u=[],s=[],f=[],c=[],l=[],d=[],h=[],p=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},m=function(e){return v(e),!1},y=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(t){var i={x:0,y:0},g=null,x=+new Date,w=function(e){y(l,[g,e]),i.x=e.clientX,i.y=e.clientY},V=function(){p.stop("mousemove",w),p.stop("mouseup",V)},b=function(){r=t.getBoundingClientRect()};window.addEventListener("resize",b),b(),t.addEventListener("mousemove",function(t){if(!o){var n,f=!1;i.x=t.clientX-r.left,i.y=t.clientY-r.top,e.getGraphCoordinates(i),n=a.getNodeAt(i.x,i.y),n&&g!==n?(g=n,f=f||y(u,[g])):null===n&&g!==n&&(f=f||y(s,[g]),g=null),f&&v(t)}}),t.addEventListener("mousedown",function(t){var o,u=!1;i.x=t.clientX-r.left,i.y=t.clientY-r.top,e.getGraphCoordinates(i),o=[a.getNodeAt(i.x,i.y),t],o[0]?(u=y(f,o),p.on("mousemove",w),p.on("mouseup",V),n=window.document.onselectstart,window.document.onselectstart=m,g=o[0]):g=null,u&&v(t)}),t.addEventListener("mouseup",function(t){var o,u=+new Date;i.x=t.clientX-r.left,i.y=t.clientY-r.top,e.getGraphCoordinates(i),o=[a.getNodeAt(i.x,i.y),t],o[0]&&(window.document.onselectstart=n,400>u-x&&o[0]===g?y(h,o):y(d,o),x=u,y(c,o)&&v(t))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&u.push(e),this},mouseLeave:function(e){return"function"==typeof e&&s.push(e),this},mouseDown:function(e){return"function"==typeof e&&f.push(e),this},mouseUp:function(e){return"function"==typeof e&&c.push(e),this},mouseMove:function(e){return"function"==typeof e&&l.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&h.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t,e),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.ui.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.ui.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.ui.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.ui.id]=t}}}; \ No newline at end of file +var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.4.0",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){function e(){var e=4022871197,t=function(t){var n;for(t=""+t,n=0;t.length>n;n++){e+=t.charCodeAt(n);var r=.02519603282416938*e;e=r>>>0,r-=e,r*=e,e=r>>>0,r-=e,e+=4294967296*r}return 2.3283064365386963e-10*(e>>>0)};return t.version="Mash 0.9",t}function t(t){return function(t){var n,r,i=0,o=58,a=119,u=178,s=[],c=e();for(0===t.length&&(t=[+new Date]),n=0;256>n;n++)s[n]=c(" "),s[n]-=4.76837158203125e-7*c(" "),0>s[n]&&(s[n]+=1);for(r=0;t.length>r;r++)for(n=0;256>n;n++)s[n]-=c(t[r]),s[n]-=4.76837158203125e-7*c(t[r]),0>s[n]&&(s[n]+=1);c=null;var f=function(){var e;return i=255&i+1,o=255&o+1,a=255&a+1,u=255&u+1,e=s[i]-s[o],0>e&&(e+=1),e-=s[a],0>e&&(e+=1),e-=s[u],0>e&&(e+=1),s[i]=e,e};return f.uint32=function(){return 4294967296*f()>>>0},f.fract53=f,f.version="LFIB4 0.9",f.args=t,f}(t)}var n=new t(Array.prototype.slice.call(arguments));return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),c=Viva.Graph.Utils.events(e),f=Viva.Graph.Utils.findElementPosition,l=0,d=0,h=!1,p=0,v=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-l,y:r-d}),l=t,d=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(l=e.clientX,d=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:l,y:d}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},E=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=v(t),o=f(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},G=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",E,!1):e.addEventListener("DOMMouseScroll",E,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",E,!1):e.removeEventListener("DOMMouseScroll",E,!1)),i=t},P=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},N=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=P(e.touches[0],e.touches[1]),r=0;p>n?r=-1:n>p&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),p=n,g(e),y(e)}},_=function(e){h=!1,s.stop("touchmove",N),s.stop("touchend",_),s.stop("touchcancel",_),u=null,r&&r(e)},L=function(e,n){g(e),y(e),l=n.clientX,d=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:l,y:d}),h||(h=!0,s.on("touchmove",N),s.on("touchend",_),s.on("touchcancel",_))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?L(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),p=P(t.touches[0],t.touches[1])),void 0)};return c.on("mousedown",V),c.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return G(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",N),s.stop("touchend",_),s.stop("touchcancel",_),G(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(){return{bindDragNDrop:function(e,t){if(t){var n=Viva.Graph.Utils.dragndrop(e.ui);"function"==typeof t.onStart&&n.onStart(t.onStart),"function"==typeof t.onDrag&&n.onDrag(t.onDrag),"function"==typeof t.onStop&&n.onStop(t.onStop),e.events=n}else e.events&&(e.events.release(),e.events=null,delete e.events)}}},Viva.Graph.spatialIndex=function(e,t){var n,r,i=16;return"function"==typeof t?(r=t,n=function(t,n){var i=null;return e.forEachNode(function(e){return r(e,t,n)?(i=e,!0):void 0}),i}):"number"==typeof t&&(i=t,n=function(t,n){var r=null;return e.forEachNode(function(e){var o=e.position;return t>o.x-i&&o.x+i>t&&n>o.y-i&&o.y+i>n?(r=e,!0):void 0}),r}),{getNodeAt:n}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,c,f,l,d,h,p,v,m,g,y,x,w,V={x:0,y:0};return s=r-t,f=e-n,d=n*t-e*r,m=s*i+f*o+d,g=s*a+f*u+d,0!==m&&0!==g&&m>=0==g>=4?null:(c=u-o,l=i-a,h=a*o-i*u,p=c*e+l*t+h,v=c*n+l*r+h,0!==p&&0!==v&&p>=0==v>=0?null:(y=s*l-c*f,0===y?null:(x=0>y?-y/2:y/2,x=0,w=f*h-l*d,V.x=(0>w?w-x:w+x)/y,w=c*d-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,c=a.y-e.y,f=s*s+c*c;for(r=1;o.length>r;++r){a=o[r];var l=i(a);l===u?(s=a.x-e.x,c=a.y-e.y,n=s*s+c*c,f>n?o.splice(r,1):o.splice(r-1,1)):u=l}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n){this.fromId=e,this.toId=t,this.data=n},Viva.Graph.graph=function(){var e={},t=[],n=0,r=0,i=[],o=function(e){e.fire("changed",i)},a=function(){r+=1},u=function(e){r-=1,0===r&&i.length>0&&(o(e),i.length=0)},s=function(e,t){i.push({node:e,changeType:t})},c=function(e,t){i.push({link:e,changeType:t})},f=function(e){return e&&"object"==typeof e&&"number"==typeof e.length&&"function"==typeof e.splice&&!e.propertyIsEnumerable("length")},l={addNode:function(t,r){if(t===void 0)throw{message:"Invalid node identifier"};a();var i=this.getNode(t);if(i?s(i,"update"):(i=new Viva.Graph.Node(t),n++,s(i,"add")),r){var o,c=i.data||{},l=typeof r;if("string"===l||f(r)||"number"===l||"boolean"===l)c=r;else if("undefined"===l)c=null;else for(o in r)r.hasOwnProperty(o)&&(c[o]=r[o]);i.data=c}return e[t]=i,u(this),i},addLink:function(e,n,r){a();var i=this.getNode(e)||this.addNode(e),o=this.getNode(n)||this.addNode(n),s=new Viva.Graph.Link(e,n,r);return t.push(s),i.links.push(s),o.links.push(s),c(s,"add"),u(this),s},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;a(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),u(this),!0},removeNode:function(t){var r=this.getNode(t);if(!r)return!1;for(a();r.links.length;){var i=r.links[0];this.removeLink(i)}e[t]=null,delete e[t],n--,s(r,"remove"),u(this)},getNode:function(t){return e[t]},getNodesCount:function(){return n},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n;if("function"==typeof e)for(n=0;t.length>n;++n)e(t[n])},beginUpdate:function(){a()},endUpdate:function(){u(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(l).extend(),l},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var c=u.velocity.x,f=u.velocity.y,l=Math.sqrt(c*c+f*f);l>r&&(u.velocity.x=r*c/l,u.velocity.y=r*f/l),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},c=[],f=0,l=function(){var e;return c[f]?(e=c[f],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,c[f]=e),++f,e},d=l(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return.01>n&&.01>r},p=function(e){for(o.reset(),o.push(d,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,c=n.left,f=(n.right+c)/2,p=n.top,v=(n.bottom+p)/2;if(i>f){s+=1;var m=c;c=f,f+=f-m}if(a>v){s+=2;var g=p;p=v,v+=v-g}var y=n.quads[s];y||(y=l(),y.left=c,y.top=p,y.right=f,y.bottom=v,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){var w,V;do{var b=2*u.nextDouble()*Math.PI,E=.006*(n.right-n.left)*Math.cos(b),G=.006*(n.bottom-n.top)*Math.sin(b);w=x.location.x+E,V=x.location.y+G}while(n.left>w||w>n.right||n.top>V||V>n.bottom);x.location.x=w,x.location.y=V}o.push(n,x),o.push(n,r)}else n.body=r}},v=function(e){var t,n,o,s,c=i,f=1,l=0,h=1;for(c[0]=d;f;){var p=c[l],v=p.body;f-=1,l+=1,v&&v!==e?(n=v.location.x-e.location.x,o=v.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=p.massX/p.mass-e.location.x,o=p.massY/p.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(p.right-p.left)/s?(t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(p.quads[0]&&(c[h]=p.quads[0],f+=1,h+=1),p.quads[1]&&(c[h]=p.quads[1],f+=1,h+=1),p.quads[2]&&(c[h]=p.quads[2],f+=1,h+=1),p.quads[3]&&(c[h]=p.quads[3],f+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,c=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>c&&(r=c),c>o&&(o=c)}var h=i-n,v=o-r;for(h>v?o=r+h:i=n+v,f=0,d=l(),d.left=n,d.right=i,d.top=r,d.bottom=o,t=u;t--;)p(a[t],d)};return{insert:p,init:m,update:v,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{init:function(){},update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{init:function(){},update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var c=s-o,f=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*c/s*n.weight;r.force.x+=f*a,r.force.y+=f*u,i.force.x+=-f*a,i.force.y+=-f*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t=e,n=[],r=[],i=[],o=[];return{speedLimit:1,bodies:n,accumulate:function(){var e,t,a;for(e=i.length;e--;)i[e].init(this);for(e=o.length;e--;)o[e].init(this);for(e=n.length;e--;)for(a=n[e],a.force.x=0,a.force.y=0,t=0;i.length>t;t++)i[t].update(a);for(e=0;r.length>e;++e)for(t=0;o.length>t;t++)o[t].update(r[e])},run:function(e){return this.accumulate(),t.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return n.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,n);return 0>t?!1:n.splice(t,1)},addSpring:function(e,t,n,i,o){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};o="number"==typeof o?o:1;var a=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,o);return r.push(a),a},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,r);return 0>t?!1:r.splice(t,1)},addBodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};i.push(e)},addSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};o.push(e)}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),c=function(n){var r=(u.x1+u.x2)/2,i=(u.y1+u.y2)/2,o=t.springLength;if(n.links&&n.links.length>0){var a=n.links[0],c=a.fromId!==n.id?e.getNode(a.fromId):e.getNode(a.toId);c.position&&(r=c.position.x,i=c.position.y)}return{x:r+s.next(o)-o/2,y:i+s.next(o)-o/2}},f=function(t){var n=t.force_directed_body;n.mass=1+e.getLinks(t.id).length/3},l=function(e){var t=e.force_directed_body;t||(e.position=e.position||c(e),t=new Viva.Graph.Physics.Body,e.force_directed_body=t,f(e),t.loc(e.position),r.addBody(t))},d=function(e){var t=e.force_directed_body;t&&(e.force_directed_body=null,delete e.force_directed_body,r.removeBody(t))},h=function(t){var n=e.getNode(t.fromId),i=e.getNode(t.toId);f(n),f(i),t.force_directed_spring=r.addSpring(n.force_directed_body,i.force_directed_body,-1,t.weight)},p=function(t){var n=t.force_directed_spring;if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&f(i),o&&f(o),t.force_directed_spring=null,delete t.force_directed_spring,r.removeSpring(n)}},v=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&l(n.node),n.link&&h(n.link)):"remove"===n.changeType&&(n.node&&d(n.node),n.link&&p(n.link))}},m=function(){e.forEachNode(l),e.forEachLink(h),e.addEventListener("changed",v)},g=function(e){return e?e.isPinned||e.data&&e.data.isPinned:!0},y=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;0!==e.getNodesCount()&&(e.forEachNode(function(e){var o=e.force_directed_body;o&&(g(e)&&o.loc(e.position),e.position.x=o.location.x,e.position.y=o.location.y,t>e.position.x&&(t=e.position.x),e.position.x>r&&(r=e.position.x),n>e.position.y&&(n=e.position.y),e.position.y>i&&(i=e.position.y))}),u.x1=t,u.x2=r,u.y1=n,u.y2=i)};return r.addSpringForce(o),r.addBodyForce(i),r.addBodyForce(a),m(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(20);return y(),n>e},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",v)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.position.xt.x2&&(t.x2=e.position.x),e.position.yt.y2&&(t.y2=e.position.y)},a=function(e){e.hasOwnProperty("position")||(e.position=i(e)),o(e,r)},u=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(a))},s=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&a(n.node)}};return{run:function(){this.step()},step:function(){return u(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",s)},placeNode:function(e){return"function"==typeof e?(i=e,u(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,c=t.container,f=!1,l=!0,d=0,h=0,p=!1,v=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){c=c||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:c}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x={x:0,y:0,node:null},w={x:0,y:0,node:null},V={x:0,y:0},b=Viva.Graph.Utils.events(window),E=Viva.Graph.Utils.events({}).extend(),G=function(t){var n=e.getNode(t.fromId),r=e.getNode(t.toId);n&&r&&(x.x=n.position.x,x.y=n.position.y,x.node=n,w.x=r.position.x,w.y=r.position.y,w.node=r,s.updateLinkPosition(t.ui,x,w))},P=function(e){V.x=e.position.x,V.y=e.position.y,s.updateNodePosition(e.ui,V)},N=function(){s.beginRender(),t.renderLinks&&!s.omitLinksRendering&&e.forEachLink(G),e.forEachNode(P),s.endRender()},_=function(){return p=u.step()&&!v,N(),!p},L=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return _()},n)):(d=0,h=0,i=Viva.Graph.Utils.timer(_,n)),void 0)},A=function(){p=!1,i.restart()},I=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},k=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(c);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),l=!1},T=function(e){var t=s.node(e);e.ui=t,s.initNode(t),P(e)},C=function(e){e.hasOwnProperty("ui")&&(s.releaseNode(e.ui),e.ui=null,delete e.ui)},M=function(e){var t=s.link(e);e.ui=t,s.initLink(t),s.omitLinksRendering||G(e)},S=function(e){e.hasOwnProperty("ui")&&(s.releaseLink(e.ui),e.ui=null,delete e.ui)},U=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=e.isPinned,e.isPinned=!0,v=!0,A()},onDrag:function(t,n){e.position.x+=n.x/g.scale,e.position.y+=n.y/g.scale,v=!0,N()},onStop:function(){e.isPinned=t,v=!1}})},R=function(e){r.bindDragNDrop(e,null)},D=function(){s.init(c),e.forEachNode(T),t.renderLinks&&e.forEachLink(M)},F=function(){s.release(c)},O=function(t){var n=t.node;"add"===t.changeType?(T(n),U(n),l&&k()):"remove"===t.changeType?(R(n),C(n),0===e.getNodesCount()&&(l=!0)):"update"===t.changeType&&(R(n),C(n),T(n),U(n))},z=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&M(n);else if("remove"===e.changeType)t.renderLinks&&S(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},B=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?O(n):n.link&&z(n);A()},Y=function(){k(),_()},X=function(){a&&(a.release(),a=null)},q=function(){o&&(o.stop("changed",B),o=null)},W=function(){b.on("resize",Y),X(),a=Viva.Graph.Utils.dragndrop(c),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),N()}),a.onScroll(function(e,t,n){var r=Math.pow(1.4,0>t?-.2:.2);g.scale=s.scale(r,n),N(),E.fire("scale",g.scale)}),e.forEachNode(U),q(),o=Viva.Graph.Utils.events(e),o.on("changed",B)},j=function(){f=!1,q(),X(),b.stop("resize",Y),E.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&S(e)}),e.forEachNode(function(e){R(e),C(e)}),u.dispose(),F()};return{run:function(e){return f||(y(),I(),k(),D(),W(),f=!0),L(e),this},reset:function(){s.resetScale(),k(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return N(),this},dispose:function(){j()},on:function(e,t){return E.addEventListener(e,t),this},off:function(e,t){return E.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var c=n(u.nodes[a]);if(!c.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(c.id,c.data)}for(a=0;u.links.length>a;++a){var f=o(u.links[a]);if(!f.hasOwnProperty("fromId")||!f.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(f.fromId,f.toId,f.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},c={},f=[t.id],l=function(e){c.hasOwnProperty(e.id)||(f.push(e.id),c[e.id]=i+1),c[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),c[t.id]=0,s[t.id]=1;f.length;)r=f.shift(),i=c[r],o=s[r],u.push(r),e.forEachLinkedNode(r,l,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},c=t.S;for(r=0;c.length>r;r+=1)s[c[r]]=0;for(;c.length;){for(i=c.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r); +return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},c=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},f=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},l=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},d=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?l(e):(l=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,d()},translateRel:function(e,r){t+=e,n+=r,d()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return c=e,this},placeLink:function(e){return f=e,this},init:function(t){e=t,d()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){c(e,t)},updateLinkPosition:function(e,t,n){f(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var c=r.childNodes[t];if(1===c.nodeType){var f=c.attr("class"),l=c.attr("id"),d=c.nodeName;if(a&&f){for(f=f.replace(/\s+/g," ").split(" "),n=0;f.length>n;n++)if(a&&f[n]===e.substr(1)){i.push(Viva.Graph.svg(c));break}}else{if(u&&l===e.substr(1)){i.push(Viva.Graph.svg(c));break}s&&d===e&&i.push(Viva.Graph.svg(c))}i=i.concat(Viva.Graph.svg(c).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i=1,o=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},a=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},u=function(){return Viva.Graph.svg("line").attr("stroke","#999")},s=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},c=function(e){e.fire("rescaled")},f=function(){if(e){var t="matrix("+i+", 0, 0,"+i+","+n+","+r+")";e.attr("transform",t)}},l={node:function(e){return e&&"function"!=typeof e?o(e):(o=e,this)},link:function(e){return e&&"function"!=typeof e?u(e):(u=e,this)},placeNode:function(e){return a=e,this},placeLink:function(e){return s=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,f()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(o,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(o).translate(-u.x,-u.y),f=e.getCTM().multiply(s);i=f.a,n=f.e,r=f.f;var l="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",l),c(this),i},resetScale:function(){i=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),c(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),f()},release:function(e){t&&e&&e.removeChild(t)},initLink:function(t){t&&(e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t))},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){a(e,t)},updateLinkPosition:function(e,t,n){s(e,t,n)},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(l).extend(),l},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),c=e.position,f=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,c.x,c.y)||r,l=n.intersectRect(c.x-s.w/2,c.y-s.h/2,c.x+s.w/2,c.y+s.h/2,c.x,c.y,r.x,r.y)||c;o+="M"+Math.round(f.x)+" "+Math.round(f.y)+"L"+Math.round(l.x)+" "+Math.round(l.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,c=4,f=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),d=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*f),p=new Float32Array(h),v=new Uint32Array(h),m=0,g=function(){if((m+1)*f>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(v),p=t,v=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(d,l),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;p[n*c]=t.x,p[n*c+1]=t.y,p[n*c+2]=e.size,v[n*c+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(v,e.id*c,m*c,c)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,c*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,c*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,c,f=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),p=0,v=new ArrayBuffer(16*l),m=new Float32Array(v),g=new Uint32Array(v),y=function(){if((p+1)*l>v.byteLength){var e=new ArrayBuffer(2*v.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,v=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,d),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*f;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),p+=1,o=e.id},removeLink:function(e){p>0&&(p-=1),p>e.id&&p>0&&r.copyArrayPart(g,e.id*f,p*f,f)},updateTransform:function(e){c=!0,s=e},updateSize:function(e,t){a=e,u=t,c=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,v,t.DYNAMIC_DRAW),c&&(c=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*p),o=p-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*f,o*f,f),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],c=[],f=function(e){return 0===(e&e-1)},l=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},d=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},p=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},v=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=d(e),o={offset:e};r.textureNumber>=s.length&&l();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),c[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!f(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=d(t.offset),r=d(o);v(r,n);var i=a[c[o]];return i.offset=t.offset,c[t.offset]=c[o],p(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){p(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,c,f=18,l=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),d=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,p=0,v=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(d,l),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*f;v[n]=t.x-e.size,v[n+1]=t.y-e.size,v[n+2]=4*e._offset,v[n+3]=t.x+e.size,v[n+4]=t.y-e.size,v[n+5]=4*e._offset+1,v[n+6]=t.x-e.size,v[n+7]=t.y+e.size,v[n+8]=4*e._offset+2,v[n+9]=t.x-e.size,v[n+10]=t.y+e.size,v[n+11]=4*e._offset+2,v[n+12]=t.x+e.size,v[n+13]=t.y-e.size,v[n+14]=4*e._offset+1,v[n+15]=t.x+e.size,v[n+16]=t.y+e.size,v[n+17]=4*e._offset+3},createNode:function(t){v=i.extendArray(v,p,f),p+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){p>0&&(p-=1),p>t.id&&p>0&&(t.src&&e.remove(t.src),i.copyArrayPart(v,t.id*f,p*f,f))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){c=!0,s=e},updateSize:function(e,t){a=e,u=t,c=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,v,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*p)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,c,f=0,l=0,d=[],h=[],p=Viva.Graph.View.webglLinkProgram(),v=Viva.Graph.View.webglNodeProgram(),m=function(){return Viva.Graph.View.webglSquare()},g=function(){return Viva.Graph.View.webglLine(3014898687)},y=function(){p.updateTransform(a),v.updateTransform(a)},x=function(){a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},w=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),p&&p.updateSize(i/2,o/2),v&&v.updateSize(i/2,o/2))},V=function(e){var t=f++,n=m(e);return n.id=t,v.createNode(n),d[t]=e,n},b=function(e){var t=l++,n=g(e);return n.id=t,p.createLink(n),h[t]=e,n},E=function(e){e.fire("rescaled")},G={node:function(e){return e&&"function"!=typeof e?V(e):(m=e,this)},link:function(e){return e&&"function"!=typeof e?b(e):(g=e,this)},placeNode:function(e){return u=e,this},placeLink:function(e){return s=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){l>0&&p.render(),f>0&&v.render()},bringLinkToFront:function(e){var t,n,r=p.getFrontLinkId();p.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].ui.id=r,h[t]=n,h[t].ui.id=t)},graphCenterChanged:function(){w()},initLink:function(){},initNode:function(){},translateRel:function(e,t){a[12]+=2*a[0]*e/i/a[0],a[13]-=2*a[5]*t/o/a[5],y()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=a[12],r-=a[13],a[12]+=n*(1-e),a[13]+=r*(1-e),a[0]*=e,a[5]*=e,y(),E(this),a[0]},resetScale:function(){return x(),r&&(w(),y()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),w(),x(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var s="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(s),s}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var f=e.clearColorValue;r.clearColor(f.r,f.g,f.b,f.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}p.load(r),p.updateSize(i/2,o/2),v.load(r),v.updateSize(i/2,o/2),y(),"function"==typeof c&&c(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){l>0&&(l-=1),p.removeLink(e);var t=e.id;if(l>t){if(0===l||l===t)return;h[t]=h[l],h[t].ui.id=t}},releaseNode:function(e){if(f>0&&(f-=1),v.removeNode(e),f>e.id){var t=e.id;if(0===f||f===t)return;var n=d[f],r=d[t];d[t]=n,d[t].ui.id=t,v.replaceProperties(r.ui,n.ui)}},updateNodePosition:function(e,t){t.y=-t.y,u&&u(e,t),v.position(e,t)},updateLinkPosition:function(e,t,n){t.y=-t.y,n.y=-n.y,s&&s(e,t,n),p.position(e,t,n)},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):c=e),n},setNodeProgram:function(e){if(!r&&e)v=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)p=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},getGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-a[12])/a[0],e.y=(e.y-a[13])/a[5],e.x*=i/2,e.y*=-o/2,e}};return Viva.Graph.Utils.events(G).extend(),G},Viva.Graph.webglInputEvents=function(e,t){if(e.webglInputEvents)return e.webglInputEvents;var n,r,i=function(e,t,n){if(e.ui&&e.ui.size){var r=e.position,i=e.ui.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},o=null,a=Viva.Graph.spatialIndex(t,i),u=[],s=[],c=[],f=[],l=[],d=[],h=[],p=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},m=function(e){return v(e),!1},g=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},y=function(t){var i={x:0,y:0},y=null,x=+new Date,w=function(e){g(l,[y,e]),i.x=e.clientX,i.y=e.clientY},V=function(){p.stop("mousemove",w),p.stop("mouseup",V)},b=function(){r=t.getBoundingClientRect()};window.addEventListener("resize",b),b(),t.addEventListener("mousemove",function(t){if(!o){var n,c=!1;i.x=t.clientX-r.left,i.y=t.clientY-r.top,e.getGraphCoordinates(i),n=a.getNodeAt(i.x,i.y),n&&y!==n?(y=n,c=c||g(u,[y])):null===n&&y!==n&&(c=c||g(s,[y]),y=null),c&&v(t)}}),t.addEventListener("mousedown",function(t){var o,u=!1;i.x=t.clientX-r.left,i.y=t.clientY-r.top,e.getGraphCoordinates(i),o=[a.getNodeAt(i.x,i.y),t],o[0]?(u=g(c,o),p.on("mousemove",w),p.on("mouseup",V),n=window.document.onselectstart,window.document.onselectstart=m,y=o[0]):y=null,u&&v(t)}),t.addEventListener("mouseup",function(t){var o,u=+new Date;i.x=t.clientX-r.left,i.y=t.clientY-r.top,e.getGraphCoordinates(i),o=[a.getNodeAt(i.x,i.y),t],o[0]&&(window.document.onselectstart=n,400>u-x&&o[0]===y?g(h,o):g(d,o),x=u,g(f,o)&&v(t))})};return e.getGraphicsRoot(y),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&u.push(e),this},mouseLeave:function(e){return"function"==typeof e&&s.push(e),this},mouseDown:function(e){return"function"==typeof e&&c.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&l.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&h.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t,e),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.ui.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.ui.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.ui.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.ui.id]=t}}}; \ No newline at end of file diff --git a/src/View/renderer.js b/src/View/renderer.js index 8573447..5689f4b 100644 --- a/src/View/renderer.js +++ b/src/View/renderer.js @@ -277,13 +277,11 @@ Viva.Graph.View.renderer = function (graph, settings) { updateCenterRequired = true; // Next time when node is added - center the graph. } } else if (change.changeType === 'update') { + releaseNodeEvents(node); + removeNodeUi(node); - // releaseNodeEvents(node); - // removeNodeUi(node); - - // createNodeUi(node); - // listenNodeEvents(node); - throw 'Update type is not implemented. TODO: Implement me!'; + createNodeUi(node); + listenNodeEvents(node); } }, From 4327dca0acfea3116104fb8fda364cf1ac847ad3 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 20 Jul 2013 16:39:46 -0700 Subject: [PATCH 007/276] Version bump --- dist/vivagraph.js | 3 ++- dist/vivagraph.min.js | 2 +- src/version.js | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 358b4fb..01bb0a4 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -7,7 +7,8 @@ Viva.Graph = Viva.Graph || {}; if (typeof module !== 'undefined' && module.exports) { module.exports = Viva; } -Viva.Graph.version = '0.4.0';/** +Viva.Graph.version = '0.4.1'; +/** * Extends target object with given fields/values in the options object. * Unlike jQuery's extend this method does not override target object * properties if their type matches corresponding type in the options object diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 2779a6b..fb23262 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.4.0",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){function e(){var e=4022871197,t=function(t){var n;for(t=""+t,n=0;t.length>n;n++){e+=t.charCodeAt(n);var r=.02519603282416938*e;e=r>>>0,r-=e,r*=e,e=r>>>0,r-=e,e+=4294967296*r}return 2.3283064365386963e-10*(e>>>0)};return t.version="Mash 0.9",t}function t(t){return function(t){var n,r,i=0,o=58,a=119,u=178,s=[],c=e();for(0===t.length&&(t=[+new Date]),n=0;256>n;n++)s[n]=c(" "),s[n]-=4.76837158203125e-7*c(" "),0>s[n]&&(s[n]+=1);for(r=0;t.length>r;r++)for(n=0;256>n;n++)s[n]-=c(t[r]),s[n]-=4.76837158203125e-7*c(t[r]),0>s[n]&&(s[n]+=1);c=null;var f=function(){var e;return i=255&i+1,o=255&o+1,a=255&a+1,u=255&u+1,e=s[i]-s[o],0>e&&(e+=1),e-=s[a],0>e&&(e+=1),e-=s[u],0>e&&(e+=1),s[i]=e,e};return f.uint32=function(){return 4294967296*f()>>>0},f.fract53=f,f.version="LFIB4 0.9",f.args=t,f}(t)}var n=new t(Array.prototype.slice.call(arguments));return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),c=Viva.Graph.Utils.events(e),f=Viva.Graph.Utils.findElementPosition,l=0,d=0,h=!1,p=0,v=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-l,y:r-d}),l=t,d=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(l=e.clientX,d=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:l,y:d}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},E=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=v(t),o=f(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},G=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",E,!1):e.addEventListener("DOMMouseScroll",E,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",E,!1):e.removeEventListener("DOMMouseScroll",E,!1)),i=t},P=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},N=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=P(e.touches[0],e.touches[1]),r=0;p>n?r=-1:n>p&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),p=n,g(e),y(e)}},_=function(e){h=!1,s.stop("touchmove",N),s.stop("touchend",_),s.stop("touchcancel",_),u=null,r&&r(e)},L=function(e,n){g(e),y(e),l=n.clientX,d=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:l,y:d}),h||(h=!0,s.on("touchmove",N),s.on("touchend",_),s.on("touchcancel",_))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?L(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),p=P(t.touches[0],t.touches[1])),void 0)};return c.on("mousedown",V),c.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return G(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",N),s.stop("touchend",_),s.stop("touchcancel",_),G(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(){return{bindDragNDrop:function(e,t){if(t){var n=Viva.Graph.Utils.dragndrop(e.ui);"function"==typeof t.onStart&&n.onStart(t.onStart),"function"==typeof t.onDrag&&n.onDrag(t.onDrag),"function"==typeof t.onStop&&n.onStop(t.onStop),e.events=n}else e.events&&(e.events.release(),e.events=null,delete e.events)}}},Viva.Graph.spatialIndex=function(e,t){var n,r,i=16;return"function"==typeof t?(r=t,n=function(t,n){var i=null;return e.forEachNode(function(e){return r(e,t,n)?(i=e,!0):void 0}),i}):"number"==typeof t&&(i=t,n=function(t,n){var r=null;return e.forEachNode(function(e){var o=e.position;return t>o.x-i&&o.x+i>t&&n>o.y-i&&o.y+i>n?(r=e,!0):void 0}),r}),{getNodeAt:n}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,c,f,l,d,h,p,v,m,g,y,x,w,V={x:0,y:0};return s=r-t,f=e-n,d=n*t-e*r,m=s*i+f*o+d,g=s*a+f*u+d,0!==m&&0!==g&&m>=0==g>=4?null:(c=u-o,l=i-a,h=a*o-i*u,p=c*e+l*t+h,v=c*n+l*r+h,0!==p&&0!==v&&p>=0==v>=0?null:(y=s*l-c*f,0===y?null:(x=0>y?-y/2:y/2,x=0,w=f*h-l*d,V.x=(0>w?w-x:w+x)/y,w=c*d-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,c=a.y-e.y,f=s*s+c*c;for(r=1;o.length>r;++r){a=o[r];var l=i(a);l===u?(s=a.x-e.x,c=a.y-e.y,n=s*s+c*c,f>n?o.splice(r,1):o.splice(r-1,1)):u=l}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n){this.fromId=e,this.toId=t,this.data=n},Viva.Graph.graph=function(){var e={},t=[],n=0,r=0,i=[],o=function(e){e.fire("changed",i)},a=function(){r+=1},u=function(e){r-=1,0===r&&i.length>0&&(o(e),i.length=0)},s=function(e,t){i.push({node:e,changeType:t})},c=function(e,t){i.push({link:e,changeType:t})},f=function(e){return e&&"object"==typeof e&&"number"==typeof e.length&&"function"==typeof e.splice&&!e.propertyIsEnumerable("length")},l={addNode:function(t,r){if(t===void 0)throw{message:"Invalid node identifier"};a();var i=this.getNode(t);if(i?s(i,"update"):(i=new Viva.Graph.Node(t),n++,s(i,"add")),r){var o,c=i.data||{},l=typeof r;if("string"===l||f(r)||"number"===l||"boolean"===l)c=r;else if("undefined"===l)c=null;else for(o in r)r.hasOwnProperty(o)&&(c[o]=r[o]);i.data=c}return e[t]=i,u(this),i},addLink:function(e,n,r){a();var i=this.getNode(e)||this.addNode(e),o=this.getNode(n)||this.addNode(n),s=new Viva.Graph.Link(e,n,r);return t.push(s),i.links.push(s),o.links.push(s),c(s,"add"),u(this),s},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;a(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),u(this),!0},removeNode:function(t){var r=this.getNode(t);if(!r)return!1;for(a();r.links.length;){var i=r.links[0];this.removeLink(i)}e[t]=null,delete e[t],n--,s(r,"remove"),u(this)},getNode:function(t){return e[t]},getNodesCount:function(){return n},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n;if("function"==typeof e)for(n=0;t.length>n;++n)e(t[n])},beginUpdate:function(){a()},endUpdate:function(){u(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(l).extend(),l},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var c=u.velocity.x,f=u.velocity.y,l=Math.sqrt(c*c+f*f);l>r&&(u.velocity.x=r*c/l,u.velocity.y=r*f/l),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},c=[],f=0,l=function(){var e;return c[f]?(e=c[f],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,c[f]=e),++f,e},d=l(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return.01>n&&.01>r},p=function(e){for(o.reset(),o.push(d,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,c=n.left,f=(n.right+c)/2,p=n.top,v=(n.bottom+p)/2;if(i>f){s+=1;var m=c;c=f,f+=f-m}if(a>v){s+=2;var g=p;p=v,v+=v-g}var y=n.quads[s];y||(y=l(),y.left=c,y.top=p,y.right=f,y.bottom=v,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){var w,V;do{var b=2*u.nextDouble()*Math.PI,E=.006*(n.right-n.left)*Math.cos(b),G=.006*(n.bottom-n.top)*Math.sin(b);w=x.location.x+E,V=x.location.y+G}while(n.left>w||w>n.right||n.top>V||V>n.bottom);x.location.x=w,x.location.y=V}o.push(n,x),o.push(n,r)}else n.body=r}},v=function(e){var t,n,o,s,c=i,f=1,l=0,h=1;for(c[0]=d;f;){var p=c[l],v=p.body;f-=1,l+=1,v&&v!==e?(n=v.location.x-e.location.x,o=v.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=p.massX/p.mass-e.location.x,o=p.massY/p.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(p.right-p.left)/s?(t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(p.quads[0]&&(c[h]=p.quads[0],f+=1,h+=1),p.quads[1]&&(c[h]=p.quads[1],f+=1,h+=1),p.quads[2]&&(c[h]=p.quads[2],f+=1,h+=1),p.quads[3]&&(c[h]=p.quads[3],f+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,c=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>c&&(r=c),c>o&&(o=c)}var h=i-n,v=o-r;for(h>v?o=r+h:i=n+v,f=0,d=l(),d.left=n,d.right=i,d.top=r,d.bottom=o,t=u;t--;)p(a[t],d)};return{insert:p,init:m,update:v,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{init:function(){},update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{init:function(){},update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var c=s-o,f=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*c/s*n.weight;r.force.x+=f*a,r.force.y+=f*u,i.force.x+=-f*a,i.force.y+=-f*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t=e,n=[],r=[],i=[],o=[];return{speedLimit:1,bodies:n,accumulate:function(){var e,t,a;for(e=i.length;e--;)i[e].init(this);for(e=o.length;e--;)o[e].init(this);for(e=n.length;e--;)for(a=n[e],a.force.x=0,a.force.y=0,t=0;i.length>t;t++)i[t].update(a);for(e=0;r.length>e;++e)for(t=0;o.length>t;t++)o[t].update(r[e])},run:function(e){return this.accumulate(),t.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return n.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,n);return 0>t?!1:n.splice(t,1)},addSpring:function(e,t,n,i,o){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};o="number"==typeof o?o:1;var a=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,o);return r.push(a),a},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,r);return 0>t?!1:r.splice(t,1)},addBodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};i.push(e)},addSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};o.push(e)}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),c=function(n){var r=(u.x1+u.x2)/2,i=(u.y1+u.y2)/2,o=t.springLength;if(n.links&&n.links.length>0){var a=n.links[0],c=a.fromId!==n.id?e.getNode(a.fromId):e.getNode(a.toId);c.position&&(r=c.position.x,i=c.position.y)}return{x:r+s.next(o)-o/2,y:i+s.next(o)-o/2}},f=function(t){var n=t.force_directed_body;n.mass=1+e.getLinks(t.id).length/3},l=function(e){var t=e.force_directed_body;t||(e.position=e.position||c(e),t=new Viva.Graph.Physics.Body,e.force_directed_body=t,f(e),t.loc(e.position),r.addBody(t))},d=function(e){var t=e.force_directed_body;t&&(e.force_directed_body=null,delete e.force_directed_body,r.removeBody(t))},h=function(t){var n=e.getNode(t.fromId),i=e.getNode(t.toId);f(n),f(i),t.force_directed_spring=r.addSpring(n.force_directed_body,i.force_directed_body,-1,t.weight)},p=function(t){var n=t.force_directed_spring;if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&f(i),o&&f(o),t.force_directed_spring=null,delete t.force_directed_spring,r.removeSpring(n)}},v=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&l(n.node),n.link&&h(n.link)):"remove"===n.changeType&&(n.node&&d(n.node),n.link&&p(n.link))}},m=function(){e.forEachNode(l),e.forEachLink(h),e.addEventListener("changed",v)},g=function(e){return e?e.isPinned||e.data&&e.data.isPinned:!0},y=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;0!==e.getNodesCount()&&(e.forEachNode(function(e){var o=e.force_directed_body;o&&(g(e)&&o.loc(e.position),e.position.x=o.location.x,e.position.y=o.location.y,t>e.position.x&&(t=e.position.x),e.position.x>r&&(r=e.position.x),n>e.position.y&&(n=e.position.y),e.position.y>i&&(i=e.position.y))}),u.x1=t,u.x2=r,u.y1=n,u.y2=i)};return r.addSpringForce(o),r.addBodyForce(i),r.addBodyForce(a),m(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(20);return y(),n>e},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",v)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.position.xt.x2&&(t.x2=e.position.x),e.position.yt.y2&&(t.y2=e.position.y)},a=function(e){e.hasOwnProperty("position")||(e.position=i(e)),o(e,r)},u=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(a))},s=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&a(n.node)}};return{run:function(){this.step()},step:function(){return u(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",s)},placeNode:function(e){return"function"==typeof e?(i=e,u(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,c=t.container,f=!1,l=!0,d=0,h=0,p=!1,v=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){c=c||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:c}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x={x:0,y:0,node:null},w={x:0,y:0,node:null},V={x:0,y:0},b=Viva.Graph.Utils.events(window),E=Viva.Graph.Utils.events({}).extend(),G=function(t){var n=e.getNode(t.fromId),r=e.getNode(t.toId);n&&r&&(x.x=n.position.x,x.y=n.position.y,x.node=n,w.x=r.position.x,w.y=r.position.y,w.node=r,s.updateLinkPosition(t.ui,x,w))},P=function(e){V.x=e.position.x,V.y=e.position.y,s.updateNodePosition(e.ui,V)},N=function(){s.beginRender(),t.renderLinks&&!s.omitLinksRendering&&e.forEachLink(G),e.forEachNode(P),s.endRender()},_=function(){return p=u.step()&&!v,N(),!p},L=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return _()},n)):(d=0,h=0,i=Viva.Graph.Utils.timer(_,n)),void 0)},A=function(){p=!1,i.restart()},I=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},k=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(c);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),l=!1},T=function(e){var t=s.node(e);e.ui=t,s.initNode(t),P(e)},C=function(e){e.hasOwnProperty("ui")&&(s.releaseNode(e.ui),e.ui=null,delete e.ui)},M=function(e){var t=s.link(e);e.ui=t,s.initLink(t),s.omitLinksRendering||G(e)},S=function(e){e.hasOwnProperty("ui")&&(s.releaseLink(e.ui),e.ui=null,delete e.ui)},U=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=e.isPinned,e.isPinned=!0,v=!0,A()},onDrag:function(t,n){e.position.x+=n.x/g.scale,e.position.y+=n.y/g.scale,v=!0,N()},onStop:function(){e.isPinned=t,v=!1}})},R=function(e){r.bindDragNDrop(e,null)},D=function(){s.init(c),e.forEachNode(T),t.renderLinks&&e.forEachLink(M)},F=function(){s.release(c)},O=function(t){var n=t.node;"add"===t.changeType?(T(n),U(n),l&&k()):"remove"===t.changeType?(R(n),C(n),0===e.getNodesCount()&&(l=!0)):"update"===t.changeType&&(R(n),C(n),T(n),U(n))},z=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&M(n);else if("remove"===e.changeType)t.renderLinks&&S(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},B=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?O(n):n.link&&z(n);A()},Y=function(){k(),_()},X=function(){a&&(a.release(),a=null)},q=function(){o&&(o.stop("changed",B),o=null)},W=function(){b.on("resize",Y),X(),a=Viva.Graph.Utils.dragndrop(c),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),N()}),a.onScroll(function(e,t,n){var r=Math.pow(1.4,0>t?-.2:.2);g.scale=s.scale(r,n),N(),E.fire("scale",g.scale)}),e.forEachNode(U),q(),o=Viva.Graph.Utils.events(e),o.on("changed",B)},j=function(){f=!1,q(),X(),b.stop("resize",Y),E.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&S(e)}),e.forEachNode(function(e){R(e),C(e)}),u.dispose(),F()};return{run:function(e){return f||(y(),I(),k(),D(),W(),f=!0),L(e),this},reset:function(){s.resetScale(),k(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return N(),this},dispose:function(){j()},on:function(e,t){return E.addEventListener(e,t),this},off:function(e,t){return E.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var c=n(u.nodes[a]);if(!c.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(c.id,c.data)}for(a=0;u.links.length>a;++a){var f=o(u.links[a]);if(!f.hasOwnProperty("fromId")||!f.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(f.fromId,f.toId,f.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},c={},f=[t.id],l=function(e){c.hasOwnProperty(e.id)||(f.push(e.id),c[e.id]=i+1),c[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),c[t.id]=0,s[t.id]=1;f.length;)r=f.shift(),i=c[r],o=s[r],u.push(r),e.forEachLinkedNode(r,l,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},c=t.S;for(r=0;c.length>r;r+=1)s[c[r]]=0;for(;c.length;){for(i=c.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r); +var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.4.1",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){function e(){var e=4022871197,t=function(t){var n;for(t=""+t,n=0;t.length>n;n++){e+=t.charCodeAt(n);var r=.02519603282416938*e;e=r>>>0,r-=e,r*=e,e=r>>>0,r-=e,e+=4294967296*r}return 2.3283064365386963e-10*(e>>>0)};return t.version="Mash 0.9",t}function t(t){return function(t){var n,r,i=0,o=58,a=119,u=178,s=[],c=e();for(0===t.length&&(t=[+new Date]),n=0;256>n;n++)s[n]=c(" "),s[n]-=4.76837158203125e-7*c(" "),0>s[n]&&(s[n]+=1);for(r=0;t.length>r;r++)for(n=0;256>n;n++)s[n]-=c(t[r]),s[n]-=4.76837158203125e-7*c(t[r]),0>s[n]&&(s[n]+=1);c=null;var f=function(){var e;return i=255&i+1,o=255&o+1,a=255&a+1,u=255&u+1,e=s[i]-s[o],0>e&&(e+=1),e-=s[a],0>e&&(e+=1),e-=s[u],0>e&&(e+=1),s[i]=e,e};return f.uint32=function(){return 4294967296*f()>>>0},f.fract53=f,f.version="LFIB4 0.9",f.args=t,f}(t)}var n=new t(Array.prototype.slice.call(arguments));return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),c=Viva.Graph.Utils.events(e),f=Viva.Graph.Utils.findElementPosition,l=0,d=0,h=!1,p=0,v=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-l,y:r-d}),l=t,d=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(l=e.clientX,d=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:l,y:d}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},E=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=v(t),o=f(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},G=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",E,!1):e.addEventListener("DOMMouseScroll",E,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",E,!1):e.removeEventListener("DOMMouseScroll",E,!1)),i=t},P=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},N=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=P(e.touches[0],e.touches[1]),r=0;p>n?r=-1:n>p&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),p=n,g(e),y(e)}},_=function(e){h=!1,s.stop("touchmove",N),s.stop("touchend",_),s.stop("touchcancel",_),u=null,r&&r(e)},L=function(e,n){g(e),y(e),l=n.clientX,d=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:l,y:d}),h||(h=!0,s.on("touchmove",N),s.on("touchend",_),s.on("touchcancel",_))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?L(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),p=P(t.touches[0],t.touches[1])),void 0)};return c.on("mousedown",V),c.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return G(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",N),s.stop("touchend",_),s.stop("touchcancel",_),G(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(){return{bindDragNDrop:function(e,t){if(t){var n=Viva.Graph.Utils.dragndrop(e.ui);"function"==typeof t.onStart&&n.onStart(t.onStart),"function"==typeof t.onDrag&&n.onDrag(t.onDrag),"function"==typeof t.onStop&&n.onStop(t.onStop),e.events=n}else e.events&&(e.events.release(),e.events=null,delete e.events)}}},Viva.Graph.spatialIndex=function(e,t){var n,r,i=16;return"function"==typeof t?(r=t,n=function(t,n){var i=null;return e.forEachNode(function(e){return r(e,t,n)?(i=e,!0):void 0}),i}):"number"==typeof t&&(i=t,n=function(t,n){var r=null;return e.forEachNode(function(e){var o=e.position;return t>o.x-i&&o.x+i>t&&n>o.y-i&&o.y+i>n?(r=e,!0):void 0}),r}),{getNodeAt:n}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,c,f,l,d,h,p,v,m,g,y,x,w,V={x:0,y:0};return s=r-t,f=e-n,d=n*t-e*r,m=s*i+f*o+d,g=s*a+f*u+d,0!==m&&0!==g&&m>=0==g>=4?null:(c=u-o,l=i-a,h=a*o-i*u,p=c*e+l*t+h,v=c*n+l*r+h,0!==p&&0!==v&&p>=0==v>=0?null:(y=s*l-c*f,0===y?null:(x=0>y?-y/2:y/2,x=0,w=f*h-l*d,V.x=(0>w?w-x:w+x)/y,w=c*d-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,c=a.y-e.y,f=s*s+c*c;for(r=1;o.length>r;++r){a=o[r];var l=i(a);l===u?(s=a.x-e.x,c=a.y-e.y,n=s*s+c*c,f>n?o.splice(r,1):o.splice(r-1,1)):u=l}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n){this.fromId=e,this.toId=t,this.data=n},Viva.Graph.graph=function(){var e={},t=[],n=0,r=0,i=[],o=function(e){e.fire("changed",i)},a=function(){r+=1},u=function(e){r-=1,0===r&&i.length>0&&(o(e),i.length=0)},s=function(e,t){i.push({node:e,changeType:t})},c=function(e,t){i.push({link:e,changeType:t})},f=function(e){return e&&"object"==typeof e&&"number"==typeof e.length&&"function"==typeof e.splice&&!e.propertyIsEnumerable("length")},l={addNode:function(t,r){if(t===void 0)throw{message:"Invalid node identifier"};a();var i=this.getNode(t);if(i?s(i,"update"):(i=new Viva.Graph.Node(t),n++,s(i,"add")),r){var o,c=i.data||{},l=typeof r;if("string"===l||f(r)||"number"===l||"boolean"===l)c=r;else if("undefined"===l)c=null;else for(o in r)r.hasOwnProperty(o)&&(c[o]=r[o]);i.data=c}return e[t]=i,u(this),i},addLink:function(e,n,r){a();var i=this.getNode(e)||this.addNode(e),o=this.getNode(n)||this.addNode(n),s=new Viva.Graph.Link(e,n,r);return t.push(s),i.links.push(s),o.links.push(s),c(s,"add"),u(this),s},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;a(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),u(this),!0},removeNode:function(t){var r=this.getNode(t);if(!r)return!1;for(a();r.links.length;){var i=r.links[0];this.removeLink(i)}e[t]=null,delete e[t],n--,s(r,"remove"),u(this)},getNode:function(t){return e[t]},getNodesCount:function(){return n},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n;if("function"==typeof e)for(n=0;t.length>n;++n)e(t[n])},beginUpdate:function(){a()},endUpdate:function(){u(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(l).extend(),l},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var c=u.velocity.x,f=u.velocity.y,l=Math.sqrt(c*c+f*f);l>r&&(u.velocity.x=r*c/l,u.velocity.y=r*f/l),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},c=[],f=0,l=function(){var e;return c[f]?(e=c[f],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,c[f]=e),++f,e},d=l(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return.01>n&&.01>r},p=function(e){for(o.reset(),o.push(d,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,c=n.left,f=(n.right+c)/2,p=n.top,v=(n.bottom+p)/2;if(i>f){s+=1;var m=c;c=f,f+=f-m}if(a>v){s+=2;var g=p;p=v,v+=v-g}var y=n.quads[s];y||(y=l(),y.left=c,y.top=p,y.right=f,y.bottom=v,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){var w,V;do{var b=2*u.nextDouble()*Math.PI,E=.006*(n.right-n.left)*Math.cos(b),G=.006*(n.bottom-n.top)*Math.sin(b);w=x.location.x+E,V=x.location.y+G}while(n.left>w||w>n.right||n.top>V||V>n.bottom);x.location.x=w,x.location.y=V}o.push(n,x),o.push(n,r)}else n.body=r}},v=function(e){var t,n,o,s,c=i,f=1,l=0,h=1;for(c[0]=d;f;){var p=c[l],v=p.body;f-=1,l+=1,v&&v!==e?(n=v.location.x-e.location.x,o=v.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=p.massX/p.mass-e.location.x,o=p.massY/p.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(p.right-p.left)/s?(t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(p.quads[0]&&(c[h]=p.quads[0],f+=1,h+=1),p.quads[1]&&(c[h]=p.quads[1],f+=1,h+=1),p.quads[2]&&(c[h]=p.quads[2],f+=1,h+=1),p.quads[3]&&(c[h]=p.quads[3],f+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,c=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>c&&(r=c),c>o&&(o=c)}var h=i-n,v=o-r;for(h>v?o=r+h:i=n+v,f=0,d=l(),d.left=n,d.right=i,d.top=r,d.bottom=o,t=u;t--;)p(a[t],d)};return{insert:p,init:m,update:v,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{init:function(){},update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{init:function(){},update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var c=s-o,f=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*c/s*n.weight;r.force.x+=f*a,r.force.y+=f*u,i.force.x+=-f*a,i.force.y+=-f*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t=e,n=[],r=[],i=[],o=[];return{speedLimit:1,bodies:n,accumulate:function(){var e,t,a;for(e=i.length;e--;)i[e].init(this);for(e=o.length;e--;)o[e].init(this);for(e=n.length;e--;)for(a=n[e],a.force.x=0,a.force.y=0,t=0;i.length>t;t++)i[t].update(a);for(e=0;r.length>e;++e)for(t=0;o.length>t;t++)o[t].update(r[e])},run:function(e){return this.accumulate(),t.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return n.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,n);return 0>t?!1:n.splice(t,1)},addSpring:function(e,t,n,i,o){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};o="number"==typeof o?o:1;var a=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,o);return r.push(a),a},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,r);return 0>t?!1:r.splice(t,1)},addBodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};i.push(e)},addSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};o.push(e)}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),c=function(n){var r=(u.x1+u.x2)/2,i=(u.y1+u.y2)/2,o=t.springLength;if(n.links&&n.links.length>0){var a=n.links[0],c=a.fromId!==n.id?e.getNode(a.fromId):e.getNode(a.toId);c.position&&(r=c.position.x,i=c.position.y)}return{x:r+s.next(o)-o/2,y:i+s.next(o)-o/2}},f=function(t){var n=t.force_directed_body;n.mass=1+e.getLinks(t.id).length/3},l=function(e){var t=e.force_directed_body;t||(e.position=e.position||c(e),t=new Viva.Graph.Physics.Body,e.force_directed_body=t,f(e),t.loc(e.position),r.addBody(t))},d=function(e){var t=e.force_directed_body;t&&(e.force_directed_body=null,delete e.force_directed_body,r.removeBody(t))},h=function(t){var n=e.getNode(t.fromId),i=e.getNode(t.toId);f(n),f(i),t.force_directed_spring=r.addSpring(n.force_directed_body,i.force_directed_body,-1,t.weight)},p=function(t){var n=t.force_directed_spring;if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&f(i),o&&f(o),t.force_directed_spring=null,delete t.force_directed_spring,r.removeSpring(n)}},v=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&l(n.node),n.link&&h(n.link)):"remove"===n.changeType&&(n.node&&d(n.node),n.link&&p(n.link))}},m=function(){e.forEachNode(l),e.forEachLink(h),e.addEventListener("changed",v)},g=function(e){return e?e.isPinned||e.data&&e.data.isPinned:!0},y=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;0!==e.getNodesCount()&&(e.forEachNode(function(e){var o=e.force_directed_body;o&&(g(e)&&o.loc(e.position),e.position.x=o.location.x,e.position.y=o.location.y,t>e.position.x&&(t=e.position.x),e.position.x>r&&(r=e.position.x),n>e.position.y&&(n=e.position.y),e.position.y>i&&(i=e.position.y))}),u.x1=t,u.x2=r,u.y1=n,u.y2=i)};return r.addSpringForce(o),r.addBodyForce(i),r.addBodyForce(a),m(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(20);return y(),n>e},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",v)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.position.xt.x2&&(t.x2=e.position.x),e.position.yt.y2&&(t.y2=e.position.y)},a=function(e){e.hasOwnProperty("position")||(e.position=i(e)),o(e,r)},u=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(a))},s=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&a(n.node)}};return{run:function(){this.step()},step:function(){return u(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",s)},placeNode:function(e){return"function"==typeof e?(i=e,u(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,c=t.container,f=!1,l=!0,d=0,h=0,p=!1,v=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){c=c||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:c}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x={x:0,y:0,node:null},w={x:0,y:0,node:null},V={x:0,y:0},b=Viva.Graph.Utils.events(window),E=Viva.Graph.Utils.events({}).extend(),G=function(t){var n=e.getNode(t.fromId),r=e.getNode(t.toId);n&&r&&(x.x=n.position.x,x.y=n.position.y,x.node=n,w.x=r.position.x,w.y=r.position.y,w.node=r,s.updateLinkPosition(t.ui,x,w))},P=function(e){V.x=e.position.x,V.y=e.position.y,s.updateNodePosition(e.ui,V)},N=function(){s.beginRender(),t.renderLinks&&!s.omitLinksRendering&&e.forEachLink(G),e.forEachNode(P),s.endRender()},_=function(){return p=u.step()&&!v,N(),!p},L=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return _()},n)):(d=0,h=0,i=Viva.Graph.Utils.timer(_,n)),void 0)},A=function(){p=!1,i.restart()},I=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},k=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(c);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),l=!1},T=function(e){var t=s.node(e);e.ui=t,s.initNode(t),P(e)},C=function(e){e.hasOwnProperty("ui")&&(s.releaseNode(e.ui),e.ui=null,delete e.ui)},M=function(e){var t=s.link(e);e.ui=t,s.initLink(t),s.omitLinksRendering||G(e)},S=function(e){e.hasOwnProperty("ui")&&(s.releaseLink(e.ui),e.ui=null,delete e.ui)},U=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=e.isPinned,e.isPinned=!0,v=!0,A()},onDrag:function(t,n){e.position.x+=n.x/g.scale,e.position.y+=n.y/g.scale,v=!0,N()},onStop:function(){e.isPinned=t,v=!1}})},R=function(e){r.bindDragNDrop(e,null)},D=function(){s.init(c),e.forEachNode(T),t.renderLinks&&e.forEachLink(M)},F=function(){s.release(c)},O=function(t){var n=t.node;"add"===t.changeType?(T(n),U(n),l&&k()):"remove"===t.changeType?(R(n),C(n),0===e.getNodesCount()&&(l=!0)):"update"===t.changeType&&(R(n),C(n),T(n),U(n))},z=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&M(n);else if("remove"===e.changeType)t.renderLinks&&S(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},B=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?O(n):n.link&&z(n);A()},Y=function(){k(),_()},X=function(){a&&(a.release(),a=null)},q=function(){o&&(o.stop("changed",B),o=null)},W=function(){b.on("resize",Y),X(),a=Viva.Graph.Utils.dragndrop(c),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),N()}),a.onScroll(function(e,t,n){var r=Math.pow(1.4,0>t?-.2:.2);g.scale=s.scale(r,n),N(),E.fire("scale",g.scale)}),e.forEachNode(U),q(),o=Viva.Graph.Utils.events(e),o.on("changed",B)},j=function(){f=!1,q(),X(),b.stop("resize",Y),E.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&S(e)}),e.forEachNode(function(e){R(e),C(e)}),u.dispose(),F()};return{run:function(e){return f||(y(),I(),k(),D(),W(),f=!0),L(e),this},reset:function(){s.resetScale(),k(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return N(),this},dispose:function(){j()},on:function(e,t){return E.addEventListener(e,t),this},off:function(e,t){return E.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var c=n(u.nodes[a]);if(!c.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(c.id,c.data)}for(a=0;u.links.length>a;++a){var f=o(u.links[a]);if(!f.hasOwnProperty("fromId")||!f.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(f.fromId,f.toId,f.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},c={},f=[t.id],l=function(e){c.hasOwnProperty(e.id)||(f.push(e.id),c[e.id]=i+1),c[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),c[t.id]=0,s[t.id]=1;f.length;)r=f.shift(),i=c[r],o=s[r],u.push(r),e.forEachLinkedNode(r,l,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},c=t.S;for(r=0;c.length>r;r+=1)s[c[r]]=0;for(;c.length;){for(i=c.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r); return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},c=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},f=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},l=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},d=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?l(e):(l=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,d()},translateRel:function(e,r){t+=e,n+=r,d()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return c=e,this},placeLink:function(e){return f=e,this},init:function(t){e=t,d()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){c(e,t)},updateLinkPosition:function(e,t,n){f(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var c=r.childNodes[t];if(1===c.nodeType){var f=c.attr("class"),l=c.attr("id"),d=c.nodeName;if(a&&f){for(f=f.replace(/\s+/g," ").split(" "),n=0;f.length>n;n++)if(a&&f[n]===e.substr(1)){i.push(Viva.Graph.svg(c));break}}else{if(u&&l===e.substr(1)){i.push(Viva.Graph.svg(c));break}s&&d===e&&i.push(Viva.Graph.svg(c))}i=i.concat(Viva.Graph.svg(c).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i=1,o=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},a=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},u=function(){return Viva.Graph.svg("line").attr("stroke","#999")},s=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},c=function(e){e.fire("rescaled")},f=function(){if(e){var t="matrix("+i+", 0, 0,"+i+","+n+","+r+")";e.attr("transform",t)}},l={node:function(e){return e&&"function"!=typeof e?o(e):(o=e,this)},link:function(e){return e&&"function"!=typeof e?u(e):(u=e,this)},placeNode:function(e){return a=e,this},placeLink:function(e){return s=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,f()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(o,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(o).translate(-u.x,-u.y),f=e.getCTM().multiply(s);i=f.a,n=f.e,r=f.f;var l="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",l),c(this),i},resetScale:function(){i=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),c(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),f()},release:function(e){t&&e&&e.removeChild(t)},initLink:function(t){t&&(e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t))},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){a(e,t)},updateLinkPosition:function(e,t,n){s(e,t,n)},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(l).extend(),l},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),c=e.position,f=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,c.x,c.y)||r,l=n.intersectRect(c.x-s.w/2,c.y-s.h/2,c.x+s.w/2,c.y+s.h/2,c.x,c.y,r.x,r.y)||c;o+="M"+Math.round(f.x)+" "+Math.round(f.y)+"L"+Math.round(l.x)+" "+Math.round(l.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,c=4,f=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),d=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*f),p=new Float32Array(h),v=new Uint32Array(h),m=0,g=function(){if((m+1)*f>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(v),p=t,v=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(d,l),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;p[n*c]=t.x,p[n*c+1]=t.y,p[n*c+2]=e.size,v[n*c+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(v,e.id*c,m*c,c)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,c*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,c*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,c,f=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),p=0,v=new ArrayBuffer(16*l),m=new Float32Array(v),g=new Uint32Array(v),y=function(){if((p+1)*l>v.byteLength){var e=new ArrayBuffer(2*v.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,v=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,d),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*f;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),p+=1,o=e.id},removeLink:function(e){p>0&&(p-=1),p>e.id&&p>0&&r.copyArrayPart(g,e.id*f,p*f,f)},updateTransform:function(e){c=!0,s=e},updateSize:function(e,t){a=e,u=t,c=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,v,t.DYNAMIC_DRAW),c&&(c=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*p),o=p-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*f,o*f,f),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],c=[],f=function(e){return 0===(e&e-1)},l=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},d=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},p=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},v=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=d(e),o={offset:e};r.textureNumber>=s.length&&l();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),c[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!f(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=d(t.offset),r=d(o);v(r,n);var i=a[c[o]];return i.offset=t.offset,c[t.offset]=c[o],p(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){p(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,c,f=18,l=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),d=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,p=0,v=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(d,l),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*f;v[n]=t.x-e.size,v[n+1]=t.y-e.size,v[n+2]=4*e._offset,v[n+3]=t.x+e.size,v[n+4]=t.y-e.size,v[n+5]=4*e._offset+1,v[n+6]=t.x-e.size,v[n+7]=t.y+e.size,v[n+8]=4*e._offset+2,v[n+9]=t.x-e.size,v[n+10]=t.y+e.size,v[n+11]=4*e._offset+2,v[n+12]=t.x+e.size,v[n+13]=t.y-e.size,v[n+14]=4*e._offset+1,v[n+15]=t.x+e.size,v[n+16]=t.y+e.size,v[n+17]=4*e._offset+3},createNode:function(t){v=i.extendArray(v,p,f),p+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){p>0&&(p-=1),p>t.id&&p>0&&(t.src&&e.remove(t.src),i.copyArrayPart(v,t.id*f,p*f,f))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){c=!0,s=e},updateSize:function(e,t){a=e,u=t,c=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,v,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*p)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,c,f=0,l=0,d=[],h=[],p=Viva.Graph.View.webglLinkProgram(),v=Viva.Graph.View.webglNodeProgram(),m=function(){return Viva.Graph.View.webglSquare()},g=function(){return Viva.Graph.View.webglLine(3014898687)},y=function(){p.updateTransform(a),v.updateTransform(a)},x=function(){a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},w=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),p&&p.updateSize(i/2,o/2),v&&v.updateSize(i/2,o/2))},V=function(e){var t=f++,n=m(e);return n.id=t,v.createNode(n),d[t]=e,n},b=function(e){var t=l++,n=g(e);return n.id=t,p.createLink(n),h[t]=e,n},E=function(e){e.fire("rescaled")},G={node:function(e){return e&&"function"!=typeof e?V(e):(m=e,this)},link:function(e){return e&&"function"!=typeof e?b(e):(g=e,this)},placeNode:function(e){return u=e,this},placeLink:function(e){return s=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){l>0&&p.render(),f>0&&v.render()},bringLinkToFront:function(e){var t,n,r=p.getFrontLinkId();p.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].ui.id=r,h[t]=n,h[t].ui.id=t)},graphCenterChanged:function(){w()},initLink:function(){},initNode:function(){},translateRel:function(e,t){a[12]+=2*a[0]*e/i/a[0],a[13]-=2*a[5]*t/o/a[5],y()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=a[12],r-=a[13],a[12]+=n*(1-e),a[13]+=r*(1-e),a[0]*=e,a[5]*=e,y(),E(this),a[0]},resetScale:function(){return x(),r&&(w(),y()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),w(),x(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var s="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(s),s}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var f=e.clearColorValue;r.clearColor(f.r,f.g,f.b,f.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}p.load(r),p.updateSize(i/2,o/2),v.load(r),v.updateSize(i/2,o/2),y(),"function"==typeof c&&c(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){l>0&&(l-=1),p.removeLink(e);var t=e.id;if(l>t){if(0===l||l===t)return;h[t]=h[l],h[t].ui.id=t}},releaseNode:function(e){if(f>0&&(f-=1),v.removeNode(e),f>e.id){var t=e.id;if(0===f||f===t)return;var n=d[f],r=d[t];d[t]=n,d[t].ui.id=t,v.replaceProperties(r.ui,n.ui)}},updateNodePosition:function(e,t){t.y=-t.y,u&&u(e,t),v.position(e,t)},updateLinkPosition:function(e,t,n){t.y=-t.y,n.y=-n.y,s&&s(e,t,n),p.position(e,t,n)},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):c=e),n},setNodeProgram:function(e){if(!r&&e)v=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)p=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},getGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-a[12])/a[0],e.y=(e.y-a[13])/a[5],e.x*=i/2,e.y*=-o/2,e}};return Viva.Graph.Utils.events(G).extend(),G},Viva.Graph.webglInputEvents=function(e,t){if(e.webglInputEvents)return e.webglInputEvents;var n,r,i=function(e,t,n){if(e.ui&&e.ui.size){var r=e.position,i=e.ui.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},o=null,a=Viva.Graph.spatialIndex(t,i),u=[],s=[],c=[],f=[],l=[],d=[],h=[],p=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},m=function(e){return v(e),!1},g=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},y=function(t){var i={x:0,y:0},y=null,x=+new Date,w=function(e){g(l,[y,e]),i.x=e.clientX,i.y=e.clientY},V=function(){p.stop("mousemove",w),p.stop("mouseup",V)},b=function(){r=t.getBoundingClientRect()};window.addEventListener("resize",b),b(),t.addEventListener("mousemove",function(t){if(!o){var n,c=!1;i.x=t.clientX-r.left,i.y=t.clientY-r.top,e.getGraphCoordinates(i),n=a.getNodeAt(i.x,i.y),n&&y!==n?(y=n,c=c||g(u,[y])):null===n&&y!==n&&(c=c||g(s,[y]),y=null),c&&v(t)}}),t.addEventListener("mousedown",function(t){var o,u=!1;i.x=t.clientX-r.left,i.y=t.clientY-r.top,e.getGraphCoordinates(i),o=[a.getNodeAt(i.x,i.y),t],o[0]?(u=g(c,o),p.on("mousemove",w),p.on("mouseup",V),n=window.document.onselectstart,window.document.onselectstart=m,y=o[0]):y=null,u&&v(t)}),t.addEventListener("mouseup",function(t){var o,u=+new Date;i.x=t.clientX-r.left,i.y=t.clientY-r.top,e.getGraphCoordinates(i),o=[a.getNodeAt(i.x,i.y),t],o[0]&&(window.document.onselectstart=n,400>u-x&&o[0]===y?g(h,o):g(d,o),x=u,g(f,o)&&v(t))})};return e.getGraphicsRoot(y),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&u.push(e),this},mouseLeave:function(e){return"function"==typeof e&&s.push(e),this},mouseDown:function(e){return"function"==typeof e&&c.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&l.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&h.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t,e),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.ui.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.ui.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.ui.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.ui.id]=t}}}; \ No newline at end of file diff --git a/src/version.js b/src/version.js index 7d1323d..fc9a685 100644 --- a/src/version.js +++ b/src/version.js @@ -1 +1 @@ -Viva.Graph.version = '0.4.0'; \ No newline at end of file +Viva.Graph.version = '0.4.1'; From ca953396a8f0ed5a007f0f47188b7c5abfa6723b Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 20 Jul 2013 17:35:14 -0700 Subject: [PATCH 008/276] Removed unnecessary whitespaces from demo files --- demos/other/communityDetection.html | 36 +++++++++---------- demos/other/constantLayout.html | 16 ++++----- demos/other/convexHull.html | 10 +++--- demos/other/d3sampleTest.html | 34 +++++++++--------- demos/other/dynamic.html | 10 +++--- demos/other/dynamicNodeChange.html | 2 +- demos/other/empty.html | 5 +-- demos/other/physicsLayout.html | 8 ++--- demos/other/pinNode.html | 12 +++---- demos/other/resetScale.html | 4 +-- demos/other/webGLRenderer.html | 12 +++---- demos/other/webglCustomNode.html | 54 ++++++++++++++--------------- demos/other/webglDynamic.html | 32 ++++++++--------- demos/other/webglInput.html | 8 ++--- 14 files changed, 120 insertions(+), 123 deletions(-) diff --git a/demos/other/communityDetection.html b/demos/other/communityDetection.html index 84172e5..c4ec59c 100644 --- a/demos/other/communityDetection.html +++ b/demos/other/communityDetection.html @@ -4,29 +4,29 @@ VivaGraphs test page - + - + - + diff --git a/demos/other/convexHull.html b/demos/other/convexHull.html index 39e26bc..b91a0bc 100644 --- a/demos/other/convexHull.html +++ b/demos/other/convexHull.html @@ -4,10 +4,10 @@ VivaGraph Convex Hull test page - + - diff --git a/demos/other/physicsLayout.html b/demos/other/physicsLayout.html index b3b9e3b..d75b12d 100644 --- a/demos/other/physicsLayout.html +++ b/demos/other/physicsLayout.html @@ -16,21 +16,21 @@ //var graph = graphGenerator.completeBipartite(10, 10); //var graph = graphGenerator.complete(100); //var graph = graphGenerator.balancedBinTree(10); - + var layout = Viva.Graph.Layout.forceDirected(graph, { springLength : 10, springCoeff : 0.0008, dragCoeff : 0.02, gravity : -1.2 }); - + var graphics = Viva.Graph.View.svgGraphics(); var renderer = Viva.Graph.View.renderer(graph, { layout : layout, graphics : graphics }); - + renderer.run(); } @@ -44,6 +44,6 @@ - + diff --git a/demos/other/pinNode.html b/demos/other/pinNode.html index b4a22b5..4a847a9 100644 --- a/demos/other/pinNode.html +++ b/demos/other/pinNode.html @@ -16,14 +16,14 @@ dragCoeff : 0.02, gravity : -1.2 }); - + var graphics = Viva.Graph.View.svgGraphics(); - // Node pinning is an attribute, which tells layout algorithm - // to not update node's position. Effectively the node looks - // like it is pinned to the canvas. + // Node pinning is an attribute, which tells layout algorithm + // to not update node's position. Effectively the node looks + // like it is pinned to the canvas. - // One way to achieve pinning is to have "isPinned" attribute on + // One way to achieve pinning is to have "isPinned" attribute on // node object: // var node = graph.addNode('yourNodeId', {some: data}); // node.isPinned = true; // now the node will not move. @@ -45,7 +45,7 @@ graphics : graphics, container : document.getElementById('graphContainer') }); - + renderer.run(); } diff --git a/demos/other/resetScale.html b/demos/other/resetScale.html index 54af7f1..b6a7908 100644 --- a/demos/other/resetScale.html +++ b/demos/other/resetScale.html @@ -16,7 +16,7 @@ dragCoeff : 0.02, gravity : -1.2 }); - + var graphics = Viva.Graph.View.svgGraphics(); var renderer = Viva.Graph.View.renderer(graph, { @@ -24,7 +24,7 @@ graphics : graphics, container : document.getElementById('graphContainer') }); - + renderer.run(); document.body.addEventListener('keydown', function (e) { if (e.which === 32) { // spacebar diff --git a/demos/other/webGLRenderer.html b/demos/other/webGLRenderer.html index c2330cc..e306bc6 100644 --- a/demos/other/webGLRenderer.html +++ b/demos/other/webGLRenderer.html @@ -18,7 +18,7 @@ //var graph = graphGenerator.ladder(1000); //var graph = Viva.Graph.graph(); //graph.addLink(1, 2); - + var layout = Viva.Graph.Layout.forceDirected(graph, { springLength : 30, springCoeff : 0.0008, @@ -26,9 +26,9 @@ gravity : -1.2, theta : 1 }); - + var graphics = Viva.Graph.View.webglGraphics(); - + var renderer = Viva.Graph.View.renderer(graph, { layout : layout, @@ -36,7 +36,7 @@ renderLinks : true, prerender : true }); - + renderer.run(); } @@ -46,13 +46,13 @@ width: 100%; position: absolute; } - canvas { + canvas { width: 100%; height: 100%; } - + diff --git a/demos/other/webglCustomNode.html b/demos/other/webglCustomNode.html index 3685e4f..1bcefff 100644 --- a/demos/other/webglCustomNode.html +++ b/demos/other/webglCustomNode.html @@ -7,7 +7,7 @@ From b71e69228ed47a914dca5332f9ddef0d0ef64c47 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 20 Jul 2013 17:42:42 -0700 Subject: [PATCH 009/276] Updated changelog --- CHANGELOG | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 2075369..131a70d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,10 @@ -v.0.4.0 +v0.4.1 + data: Jul 20, 2013 + changes: + - Layout algorithm now listens to changes from graph directly. Public API + to add/remove nodes or links is dropped from layout algorithms. + - Added small performance test for node.js +v0.4.0 date: April 7, 2013 changes: - Migrated to grunt.js as a build system From 1fd1a0d6c333b0550f253ddaea534b1c78f03b8c Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 4 Aug 2013 18:49:38 -0700 Subject: [PATCH 010/276] Updated comment --- src/Layout/forceDirected.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Layout/forceDirected.js b/src/Layout/forceDirected.js index 57f74ca..3d73e13 100644 --- a/src/Layout/forceDirected.js +++ b/src/Layout/forceDirected.js @@ -160,7 +160,6 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { releaseLink(change.link); } } - // Probably we don't need to care about 'update' event here; } }, From 7c15033cbdd0505fbad9f072080f4bd60a30c34b Mon Sep 17 00:00:00 2001 From: anvaka Date: Tue, 6 Aug 2013 21:12:26 -0700 Subject: [PATCH 011/276] Decoupling layout/ui properties from node --- dist/vivagraph.js | 382 +++++++++++++++++++++++------------ dist/vivagraph.min.js | 4 +- src/Core/graph.js | 15 +- src/Core/primitives.js | 5 +- src/Input/domInputManager.js | 17 +- src/Layout/forceDirected.js | 187 ++++++++++++----- src/View/renderer.js | 68 ++++--- src/View/svgGraphics.js | 87 +++++--- 8 files changed, 508 insertions(+), 257 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 01bb0a4..e0cc1ba 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -723,7 +723,8 @@ Viva.Graph.Utils.dragndrop = function (element) { */ Viva.Input = Viva.Input || {}; -Viva.Input.domInputManager = function () { +Viva.Input.domInputManager = function (graph, graphics) { + var nodeEvents = {}; return { /** * Called by renderer to listen to drag-n-drop events from node. E.g. for CSS/SVG @@ -737,8 +738,10 @@ Viva.Input.domInputManager = function () { * onStop: function() */ bindDragNDrop : function (node, handlers) { + var events; if (handlers) { - var events = Viva.Graph.Utils.dragndrop(node.ui); + var nodeUI = graphics.getNodeUI(node.id); + events = Viva.Graph.Utils.dragndrop(nodeUI); if (typeof handlers.onStart === 'function') { events.onStart(handlers.onStart); } @@ -749,12 +752,10 @@ Viva.Input.domInputManager = function () { events.onStop(handlers.onStop); } - node.events = events; - } else if (node.events) { - // TODO: i'm not sure if this is required in JS world... - node.events.release(); - node.events = null; - delete node.events; + nodeEvents[node.id] = events; + } else if (( events = nodeEvents[node.id] )) { + events.release(); + delete nodeEvents[node.id]; } } }; @@ -1105,11 +1106,13 @@ Viva.Graph.Node = function (id) { /** * Internal structure to represent links; */ -Viva.Graph.Link = function (fromId, toId, data) { +Viva.Graph.Link = function (fromId, toId, data, id) { this.fromId = fromId; this.toId = toId; this.data = data; -};/** + this.id = id; +}; +/** * @fileOverview Contains definition of the core graph object. * * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com @@ -1135,6 +1138,8 @@ Viva.Graph.graph = function () { var nodes = {}, links = [], + // Hash of multi-edges. Used to track ids of edges between same nodes + multiEdges = {}, nodesCount = 0, suspendEvents = 0, @@ -1257,7 +1262,16 @@ Viva.Graph.graph = function () { var fromNode = this.getNode(fromId) || this.addNode(fromId); var toNode = this.getNode(toId) || this.addNode(toId); - var link = new Viva.Graph.Link(fromId, toId, data); + var linkId = fromId.toString() + toId.toString(); + var isMultiEdge = multiEdges.hasOwnProperty(linkId); + if (isMultiEdge || this.hasLink(fromId, toId)) { + if (!isMultiEdge) { + multiEdges[linkId] = 0; + } + linkId += '@' + (++multiEdges[linkId]); + } + + var link = new Viva.Graph.Link(fromId, toId, data, linkId); links.push(link); @@ -1514,7 +1528,8 @@ Viva.Graph.graph = function () { Viva.Graph.Utils.events(graphPart).extend(); return graphPart; -};/** +}; +/** * @fileOverview Contains collection of primitve operations under graph. * * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com @@ -2237,6 +2252,12 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { } settings = Viva.lazyExtend(settings, { + /** + * If true, the layout API will be compatible with + * old version of the library, where each node had it's own + * position property. This was a bad API decision... + */ + compatible: false, /** * Ideal length for links (springs in physical model). */ @@ -2283,10 +2304,10 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { graphRect = new Viva.Graph.Rect(), random = Viva.random('ted.com', 103, 114, 101, 97, 116), - getBestNodePosition = function(node) { + getBestBodyPosition = function(node) { // TODO: Initial position could be picked better, e.g. take into // account all neighbouring nodes/links, not only one. - // TODO: this is the same as in gem layout. consider refactoring. + // How about center of mass? var baseX = (graphRect.x1 + graphRect.x2) / 2, baseY = (graphRect.y1 + graphRect.y2) / 2, springLength = settings.springLength; @@ -2306,61 +2327,94 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { }; }, - updateNodeMass = function(node) { - var body = node.force_directed_body; + nodeBodies = {}, + getBody = function (nodeId) { + return nodeBodies[nodeId]; + }, + + releaseBody = function (node) { + nodeBodies[node.id] = null; + delete nodeBodies[node.id]; + }, + + springs = {}, + + updateBodyMass = function(node) { + var body = getBody(node.id); body.mass = 1 + graph.getLinks(node.id).length / 3.0; }, initNode = function(node) { - var body = node.force_directed_body; + var body = getBody(node.id); if (!body) { - // TODO: rename position to location or location to position to be consistent with - // other places. - node.position = node.position || getBestNodePosition(node); - body = new Viva.Graph.Physics.Body(); - node.force_directed_body = body; - updateNodeMass(node); + nodeBodies[node.id] = body; + var position = getBestBodyPosition(body); + body.loc(position); + updateBodyMass(node); + + if (settings.compatible) { + // This is depricated method. Please never ever use + // 'compatible' mode: it has a curse of shared data store + // i.e. there is no way two layouters could layout the same + // graph, since they both would compete for positions + node.position = position; + node.force_directed_body = body; + } - body.loc(node.position); forceSimulator.addBody(body); } }, releaseNode = function(node) { - var body = node.force_directed_body; + var body = getBody(node.id); if (body) { - node.force_directed_body = null; - delete node.force_directed_body; + if (settings.compatible) { + node.force_directed_body = null; + delete node.force_directed_body; + } + releaseBody(node); forceSimulator.removeBody(body); } }, initLink = function(link) { - // TODO: what if bodies are not initialized? var from = graph.getNode(link.fromId), to = graph.getNode(link.toId); - updateNodeMass(from); - updateNodeMass(to); - link.force_directed_spring = forceSimulator.addSpring(from.force_directed_body, to.force_directed_body, -1.0, link.weight); + updateBodyMass(from); + updateBodyMass(to); + + var fromBody = getBody(link.fromId), + toBody = getBody(link.toId), + spring = forceSimulator.addSpring(fromBody, toBody, -1.0, link.weight); + + // TODO: this has a bug, with multiple springs between same nodes + springs[link.id] = spring; + + if (settings.compatible) { + // bad... + link.force_directed_spring = spring; + } }, releaseLink = function(link) { - var spring = link.force_directed_spring; + var spring = springs[link.id]; if (spring) { var from = graph.getNode(link.fromId), to = graph.getNode(link.toId); if (from) { - updateNodeMass(from); + updateBodyMass(from); } if (to) { - updateNodeMass(to); + updateBodyMass(to); } - - link.force_directed_spring = null; - delete link.force_directed_spring; + if (settings.compatible) { + link.force_directed_spring = null; + delete link.force_directed_spring; + } + delete springs[link.id]; forceSimulator.removeSpring(spring); } @@ -2384,7 +2438,6 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { releaseLink(change.link); } } - // Probably we don't need to care about 'update' event here; } }, @@ -2394,12 +2447,14 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { graph.addEventListener('changed', onGraphChanged); }, - isNodePinned = function(node) { - if (!node) { + isNodePinned = function(node, body) { + // this potentiall should make it easy to refactor when compatible mode goes away + if (!node && !body) { return true; } - return node.isPinned || (node.data && node.data.isPinned); + return (node && (node.isPinned || (node.data && node.data.isPinned))) || + (body && body.isPinned); }, updateNodePositions = function() { @@ -2407,39 +2462,54 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { y1 = Number.MAX_VALUE, x2 = Number.MIN_VALUE, y2 = Number.MIN_VALUE; + if (graph.getNodesCount() === 0) { return; } - - graph.forEachNode(function(node) { - var body = node.force_directed_body; - if (!body) { - // This could be a sign someone removed the propery. - // I should really decouple force related stuff from node - return; + for (var key in nodeBodies) { + if (nodeBodies.hasOwnProperty(key)) { + // how about pinned nodes? + var body = nodeBodies[key]; + if (isNodePinned(null, body)) { + body.location.x = body.prevLocation.x; + body.location.y = body.prevLocation.y; + } else { + body.prevLocation.x = body.location.x; + body.prevLocation.y = body.location.y; + } + if (body.location.x < x1) { + x1 = body.location.x; + } + if (body.location.x > x2) { + x2 = body.location.x; + } + if (body.location.y < y1) { + y1 = body.location.y; + } + if (body.location.y > y2) { + y2 = body.location.y; + } } + } - if (isNodePinned(node)) { - body.loc(node.position); - } + if (settings.compatible) { + graph.forEachNode(function(node) { + var body = node.force_directed_body; + if (!body) { + // This could be a sign someone removed the propery. + // Please don't use 'compatible' mode + return; + } - // TODO: once again: use one name to be consistent (position vs location) - node.position.x = body.location.x; - node.position.y = body.location.y; + // if (isNodePinned(node)) { + // body.loc(node.position); + // } - if (node.position.x < x1) { - x1 = node.position.x; - } - if (node.position.x > x2) { - x2 = node.position.x; - } - if (node.position.y < y1) { - y1 = node.position.y; - } - if (node.position.y > y2) { - y2 = node.position.y; - } - }); + node.position.x = body.location.x; + node.position.y = body.location.y; + + }); + } graphRect.x1 = x1; graphRect.x2 = x2; @@ -2475,6 +2545,29 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { return energy < STABLE_THRESHOLD; }, + isNodePinned: function (node) { + var body = getBody(node.id); + return isNodePinned(node, body); + }, + + pinNode: function (node, isPinned) { + var body = getBody(node.id); + body.isPinned = !!isPinned; + }, + + getNodePosition: function (nodeId) { + var body = getBody(nodeId); + return body && body.location; + }, + + setNodePosition: function (node, x, y) { + var body = getBody(node.id); + if (body) { + body.prevLocation.x = body.location.x = x; + body.prevLocation.y = body.location.y = y; + } + }, + /** * Returns rectangle structure {x1, y1, x2, y2}, which represents * current space occupied by graph. @@ -2744,7 +2837,13 @@ Viva.Graph.View = Viva.Graph.View || {}; * // Number of layout iterations to run before displaying the graph. The bigger you set this number * // the closer to ideal position graph will apper first time. But be careful: for large graphs * // it can freeze the browser. - * prerender : 0 + * prerender : 0, + * + * // Renderer should be compatible with older version of VivaGraph. + * // Warning: This option will be depricated soon. Compatible mode has a flaw of data being + * // shared on a node object of a graph. Which makes it impossible to reuse between multiple + * // renderers/layouters. + * compatible: false * } */ Viva.Graph.View.renderer = function (graph, settings) { @@ -2787,6 +2886,7 @@ Viva.Graph.View.renderer = function (graph, settings) { settings.renderLinks = true; } + settings.compatible = settings.compatible || false; settings.prerender = settings.prerender || 0; inputManager = (graphics.inputManager || Viva.Input.domInputManager)(graph, graphics); }, @@ -2801,29 +2901,28 @@ Viva.Graph.View.renderer = function (graph, settings) { renderLink = function (link) { - var fromNode = graph.getNode(link.fromId), - toNode = graph.getNode(link.toId); + var fromNode = layout.getNodePosition(link.fromId), + toNode = layout.getNodePosition(link.toId); if (!fromNode || !toNode) { return; } - cachedFromPos.x = fromNode.position.x; - cachedFromPos.y = fromNode.position.y; - cachedFromPos.node = fromNode; + cachedFromPos.x = fromNode.x; + cachedFromPos.y = fromNode.y; - cachedToPos.x = toNode.position.x; - cachedToPos.y = toNode.position.y; - cachedToPos.node = toNode; + cachedToPos.x = toNode.x; + cachedToPos.y = toNode.y; - graphics.updateLinkPosition(link.ui, cachedFromPos, cachedToPos); + graphics.updateLinkPosition(link, cachedFromPos, cachedToPos); }, renderNode = function (node) { - cachedNodePos.x = node.position.x; - cachedNodePos.y = node.position.y; + var pos = layout.getNodePosition(node.id); + cachedNodePos.x = pos.x; + cachedNodePos.y = pos.y; - graphics.updateNodePosition(node.ui, cachedNodePos); + graphics.updateNodePosition(node, cachedNodePos); }, renderGraph = function () { @@ -2891,26 +2990,27 @@ Viva.Graph.View.renderer = function (graph, settings) { }, createNodeUi = function (node) { - var nodeUI = graphics.node(node); - node.ui = nodeUI; - graphics.initNode(nodeUI); + var nodeUI = graphics.addNode(node); + if (settings.compatible) { + node.ui = nodeUI; + } renderNode(node); }, removeNodeUi = function (node) { - if (node.hasOwnProperty('ui')) { - graphics.releaseNode(node.ui); - + graphics.releaseNode(node); + if (settings.compatible && node.hasOwnProperty('ui')) { node.ui = null; delete node.ui; } }, createLinkUi = function (link) { - var linkUI = graphics.link(link); - link.ui = linkUI; - graphics.initLink(linkUI); + var linkUI = graphics.addLink(link); + if (settings.compatible) { + link.ui = linkUI; + } if (!graphics.omitLinksRendering) { renderLink(link); @@ -2918,8 +3018,8 @@ Viva.Graph.View.renderer = function (graph, settings) { }, removeLinkUi = function (link) { - if (link.hasOwnProperty('ui')) { - graphics.releaseLink(link.ui); + graphics.releaseLink(link); + if (settings.compatible && link.hasOwnProperty('ui')) { link.ui = null; delete link.ui; } @@ -2931,20 +3031,23 @@ Viva.Graph.View.renderer = function (graph, settings) { // TODO: This may not be memory efficient. Consider reusing handlers object. inputManager.bindDragNDrop(node, { onStart : function () { - wasPinned = node.isPinned; - node.isPinned = true; + wasPinned = layout.isNodePinned(node); + layout.pinNode(node, true); userInteraction = true; resetStable(); }, onDrag : function (e, offset) { - node.position.x += offset.x / transform.scale; - node.position.y += offset.y / transform.scale; + var oldPos = layout.getNodePosition(node.id); + layout.setNodePosition(node, + oldPos.x + offset.x / transform.scale, + oldPos.y + offset.y / transform.scale); + userInteraction = true; renderGraph(); }, onStop : function () { - node.isPinned = wasPinned; + layout.pinNode(node, wasPinned); userInteraction = false; } }); @@ -4419,6 +4522,8 @@ Viva.Graph.View.svgGraphics = function () { offsetX, offsetY, actualScale = 1, + allNodes = {}, + allLinks = {}, /*jshint unused: false */ nodeBuilder = function (node) { return Viva.Graph.svg("rect") @@ -4458,51 +4563,53 @@ Viva.Graph.View.svgGraphics = function () { }; var graphics = { + getNodeUI: function (nodeId) { + return allNodes[nodeId]; + }, + + getLinkUI: function (linkId) { + return allLinks[linkId]; + }, /** - * Sets the collback that creates node representation or creates a new node - * presentation if builderCallbackOrNode is not a function. + * Sets the collback that creates node representation. * - * @param builderCallbackOrNode a callback function that accepts graph node - * as a parameter and must return an element representing this node. OR - * if it's not a function it's treated as a node to which DOM element should be created. + * @param builderCallback a callback function that accepts graph node + * as a parameter and must return an element representing this node. * * @returns If builderCallbackOrNode is a valid callback function, instance of this is returned; - * Otherwise a node representation is returned for the passed parameter. + * Otherwise undefined value is returned */ - node : function (builderCallbackOrNode) { - - if (builderCallbackOrNode && typeof builderCallbackOrNode !== "function") { - return nodeBuilder(builderCallbackOrNode); + node : function (builderCallback) { + if (typeof builderCallback !== "function") { + return; // todo: throw? this is not compatible with old versions } - nodeBuilder = builderCallbackOrNode; + nodeBuilder = builderCallback; return this; }, /** - * Sets the collback that creates link representation or creates a new link - * presentation if builderCallbackOrLink is not a function. + * Sets the callback that creates link representation * - * @param builderCallbackOrLink a callback function that accepts graph link - * as a parameter and must return an element representing this link. OR - * if it's not a function it's treated as a link to which DOM element should be created. + * @param builderCallback a callback function that accepts graph link + * as a parameter and must return an element representing this link. * - * @returns If builderCallbackOrLink is a valid callback function, instance of this is returned; - * Otherwise a link representation is returned for the passed parameter. + * @returns If builderCallback is a valid callback function, instance of this is returned; + * Otherwise undefined value is returend. */ - link : function (builderCallbackOrLink) { - if (builderCallbackOrLink && typeof builderCallbackOrLink !== "function") { - return linkBuilder(builderCallbackOrLink); + link : function (builderCallback) { + if (typeof builderCallback !== "function") { + return; // todo: throw? this is not compatible with old versions } - linkBuilder = builderCallbackOrLink; + linkBuilder = builderCallback; return this; }, /** * Allows to override default position setter for the node with a new - * function. newPlaceCallback(nodeUI, position) is function which + * function. newPlaceCallback(nodeUI, position, node) is function which * is used by updateNodePosition(). */ placeNode : function (newPlaceCallback) { @@ -4618,13 +4725,16 @@ Viva.Graph.View.svgGraphics = function () { * * @param linkUI visual representation of the link created by link() execution. */ - initLink : function (linkUI) { + addLink: function (link) { + var linkUI = linkBuilder(link); if (!linkUI) { return; } + allLinks[link.id] = linkUI; if (svgContainer.childElementCount > 0) { svgContainer.insertBefore(linkUI, svgContainer.firstChild); } else { svgContainer.appendChild(linkUI); } + return linkUI; }, /** @@ -4633,7 +4743,8 @@ Viva.Graph.View.svgGraphics = function () { * * @param linkUI visual representation of the link created by link() execution. **/ - releaseLink : function (linkUI) { + releaseLink : function (link) { + var linkUI = this.getLinkUI(link); svgContainer.removeChild(linkUI); }, @@ -4643,26 +4754,40 @@ Viva.Graph.View.svgGraphics = function () { * * @param nodeUI visual representation of the node created by node() execution. **/ - initNode : function (nodeUI) { + addNode : function (node) { + var nodeUI = nodeBuilder(node); + if (!nodeUI) { + return; + } + allNodes[node.id] = nodeUI; + svgContainer.appendChild(nodeUI); + + return nodeUI; }, /** * Called by Viva.Graph.View.renderer to let concrete graphic output * provider remove node from rendering surface. * - * @param nodeUI visual representation of the node created by node() execution. + * @param node graph's node **/ - releaseNode : function (nodeUI) { - svgContainer.removeChild(nodeUI); + releaseNode : function (node) { + var nodeUI = this.getNodeUI(node.id); + if (nodeUI) { + svgContainer.removeChild(nodeUI); + } }, /** * Called by Viva.Graph.View.renderer to let concrete graphic output * provider place given node UI to recommended position pos {x, y}; */ - updateNodePosition : function (nodeUI, pos) { - nodePositionCallback(nodeUI, pos); + updateNodePosition : function (node, pos) { + var ui = this.getNodeUI(node.id); + if (ui) { + nodePositionCallback(ui, pos, node); + } }, /** @@ -4670,7 +4795,8 @@ Viva.Graph.View.svgGraphics = function () { * provider place given link of the graph. Pos objects are {x, y}; */ updateLinkPosition : function (link, fromPos, toPos) { - linkPositionCallback(link, fromPos, toPos); + var ui = this.getLinkUI(link.id); + linkPositionCallback(ui, fromPos, toPos, link); }, /** diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index fb23262..66e5381 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.4.1",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){function e(){var e=4022871197,t=function(t){var n;for(t=""+t,n=0;t.length>n;n++){e+=t.charCodeAt(n);var r=.02519603282416938*e;e=r>>>0,r-=e,r*=e,e=r>>>0,r-=e,e+=4294967296*r}return 2.3283064365386963e-10*(e>>>0)};return t.version="Mash 0.9",t}function t(t){return function(t){var n,r,i=0,o=58,a=119,u=178,s=[],c=e();for(0===t.length&&(t=[+new Date]),n=0;256>n;n++)s[n]=c(" "),s[n]-=4.76837158203125e-7*c(" "),0>s[n]&&(s[n]+=1);for(r=0;t.length>r;r++)for(n=0;256>n;n++)s[n]-=c(t[r]),s[n]-=4.76837158203125e-7*c(t[r]),0>s[n]&&(s[n]+=1);c=null;var f=function(){var e;return i=255&i+1,o=255&o+1,a=255&a+1,u=255&u+1,e=s[i]-s[o],0>e&&(e+=1),e-=s[a],0>e&&(e+=1),e-=s[u],0>e&&(e+=1),s[i]=e,e};return f.uint32=function(){return 4294967296*f()>>>0},f.fract53=f,f.version="LFIB4 0.9",f.args=t,f}(t)}var n=new t(Array.prototype.slice.call(arguments));return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),c=Viva.Graph.Utils.events(e),f=Viva.Graph.Utils.findElementPosition,l=0,d=0,h=!1,p=0,v=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-l,y:r-d}),l=t,d=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(l=e.clientX,d=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:l,y:d}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},E=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=v(t),o=f(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},G=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",E,!1):e.addEventListener("DOMMouseScroll",E,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",E,!1):e.removeEventListener("DOMMouseScroll",E,!1)),i=t},P=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},N=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=P(e.touches[0],e.touches[1]),r=0;p>n?r=-1:n>p&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),p=n,g(e),y(e)}},_=function(e){h=!1,s.stop("touchmove",N),s.stop("touchend",_),s.stop("touchcancel",_),u=null,r&&r(e)},L=function(e,n){g(e),y(e),l=n.clientX,d=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:l,y:d}),h||(h=!0,s.on("touchmove",N),s.on("touchend",_),s.on("touchcancel",_))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?L(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),p=P(t.touches[0],t.touches[1])),void 0)};return c.on("mousedown",V),c.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return G(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",N),s.stop("touchend",_),s.stop("touchcancel",_),G(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(){return{bindDragNDrop:function(e,t){if(t){var n=Viva.Graph.Utils.dragndrop(e.ui);"function"==typeof t.onStart&&n.onStart(t.onStart),"function"==typeof t.onDrag&&n.onDrag(t.onDrag),"function"==typeof t.onStop&&n.onStop(t.onStop),e.events=n}else e.events&&(e.events.release(),e.events=null,delete e.events)}}},Viva.Graph.spatialIndex=function(e,t){var n,r,i=16;return"function"==typeof t?(r=t,n=function(t,n){var i=null;return e.forEachNode(function(e){return r(e,t,n)?(i=e,!0):void 0}),i}):"number"==typeof t&&(i=t,n=function(t,n){var r=null;return e.forEachNode(function(e){var o=e.position;return t>o.x-i&&o.x+i>t&&n>o.y-i&&o.y+i>n?(r=e,!0):void 0}),r}),{getNodeAt:n}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,c,f,l,d,h,p,v,m,g,y,x,w,V={x:0,y:0};return s=r-t,f=e-n,d=n*t-e*r,m=s*i+f*o+d,g=s*a+f*u+d,0!==m&&0!==g&&m>=0==g>=4?null:(c=u-o,l=i-a,h=a*o-i*u,p=c*e+l*t+h,v=c*n+l*r+h,0!==p&&0!==v&&p>=0==v>=0?null:(y=s*l-c*f,0===y?null:(x=0>y?-y/2:y/2,x=0,w=f*h-l*d,V.x=(0>w?w-x:w+x)/y,w=c*d-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,c=a.y-e.y,f=s*s+c*c;for(r=1;o.length>r;++r){a=o[r];var l=i(a);l===u?(s=a.x-e.x,c=a.y-e.y,n=s*s+c*c,f>n?o.splice(r,1):o.splice(r-1,1)):u=l}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n){this.fromId=e,this.toId=t,this.data=n},Viva.Graph.graph=function(){var e={},t=[],n=0,r=0,i=[],o=function(e){e.fire("changed",i)},a=function(){r+=1},u=function(e){r-=1,0===r&&i.length>0&&(o(e),i.length=0)},s=function(e,t){i.push({node:e,changeType:t})},c=function(e,t){i.push({link:e,changeType:t})},f=function(e){return e&&"object"==typeof e&&"number"==typeof e.length&&"function"==typeof e.splice&&!e.propertyIsEnumerable("length")},l={addNode:function(t,r){if(t===void 0)throw{message:"Invalid node identifier"};a();var i=this.getNode(t);if(i?s(i,"update"):(i=new Viva.Graph.Node(t),n++,s(i,"add")),r){var o,c=i.data||{},l=typeof r;if("string"===l||f(r)||"number"===l||"boolean"===l)c=r;else if("undefined"===l)c=null;else for(o in r)r.hasOwnProperty(o)&&(c[o]=r[o]);i.data=c}return e[t]=i,u(this),i},addLink:function(e,n,r){a();var i=this.getNode(e)||this.addNode(e),o=this.getNode(n)||this.addNode(n),s=new Viva.Graph.Link(e,n,r);return t.push(s),i.links.push(s),o.links.push(s),c(s,"add"),u(this),s},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;a(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),u(this),!0},removeNode:function(t){var r=this.getNode(t);if(!r)return!1;for(a();r.links.length;){var i=r.links[0];this.removeLink(i)}e[t]=null,delete e[t],n--,s(r,"remove"),u(this)},getNode:function(t){return e[t]},getNodesCount:function(){return n},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n;if("function"==typeof e)for(n=0;t.length>n;++n)e(t[n])},beginUpdate:function(){a()},endUpdate:function(){u(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(l).extend(),l},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var c=u.velocity.x,f=u.velocity.y,l=Math.sqrt(c*c+f*f);l>r&&(u.velocity.x=r*c/l,u.velocity.y=r*f/l),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},c=[],f=0,l=function(){var e;return c[f]?(e=c[f],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,c[f]=e),++f,e},d=l(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return.01>n&&.01>r},p=function(e){for(o.reset(),o.push(d,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,c=n.left,f=(n.right+c)/2,p=n.top,v=(n.bottom+p)/2;if(i>f){s+=1;var m=c;c=f,f+=f-m}if(a>v){s+=2;var g=p;p=v,v+=v-g}var y=n.quads[s];y||(y=l(),y.left=c,y.top=p,y.right=f,y.bottom=v,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){var w,V;do{var b=2*u.nextDouble()*Math.PI,E=.006*(n.right-n.left)*Math.cos(b),G=.006*(n.bottom-n.top)*Math.sin(b);w=x.location.x+E,V=x.location.y+G}while(n.left>w||w>n.right||n.top>V||V>n.bottom);x.location.x=w,x.location.y=V}o.push(n,x),o.push(n,r)}else n.body=r}},v=function(e){var t,n,o,s,c=i,f=1,l=0,h=1;for(c[0]=d;f;){var p=c[l],v=p.body;f-=1,l+=1,v&&v!==e?(n=v.location.x-e.location.x,o=v.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=p.massX/p.mass-e.location.x,o=p.massY/p.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(p.right-p.left)/s?(t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(p.quads[0]&&(c[h]=p.quads[0],f+=1,h+=1),p.quads[1]&&(c[h]=p.quads[1],f+=1,h+=1),p.quads[2]&&(c[h]=p.quads[2],f+=1,h+=1),p.quads[3]&&(c[h]=p.quads[3],f+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,c=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>c&&(r=c),c>o&&(o=c)}var h=i-n,v=o-r;for(h>v?o=r+h:i=n+v,f=0,d=l(),d.left=n,d.right=i,d.top=r,d.bottom=o,t=u;t--;)p(a[t],d)};return{insert:p,init:m,update:v,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{init:function(){},update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{init:function(){},update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var c=s-o,f=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*c/s*n.weight;r.force.x+=f*a,r.force.y+=f*u,i.force.x+=-f*a,i.force.y+=-f*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t=e,n=[],r=[],i=[],o=[];return{speedLimit:1,bodies:n,accumulate:function(){var e,t,a;for(e=i.length;e--;)i[e].init(this);for(e=o.length;e--;)o[e].init(this);for(e=n.length;e--;)for(a=n[e],a.force.x=0,a.force.y=0,t=0;i.length>t;t++)i[t].update(a);for(e=0;r.length>e;++e)for(t=0;o.length>t;t++)o[t].update(r[e])},run:function(e){return this.accumulate(),t.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return n.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,n);return 0>t?!1:n.splice(t,1)},addSpring:function(e,t,n,i,o){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};o="number"==typeof o?o:1;var a=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,o);return r.push(a),a},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,r);return 0>t?!1:r.splice(t,1)},addBodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};i.push(e)},addSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};o.push(e)}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),c=function(n){var r=(u.x1+u.x2)/2,i=(u.y1+u.y2)/2,o=t.springLength;if(n.links&&n.links.length>0){var a=n.links[0],c=a.fromId!==n.id?e.getNode(a.fromId):e.getNode(a.toId);c.position&&(r=c.position.x,i=c.position.y)}return{x:r+s.next(o)-o/2,y:i+s.next(o)-o/2}},f=function(t){var n=t.force_directed_body;n.mass=1+e.getLinks(t.id).length/3},l=function(e){var t=e.force_directed_body;t||(e.position=e.position||c(e),t=new Viva.Graph.Physics.Body,e.force_directed_body=t,f(e),t.loc(e.position),r.addBody(t))},d=function(e){var t=e.force_directed_body;t&&(e.force_directed_body=null,delete e.force_directed_body,r.removeBody(t))},h=function(t){var n=e.getNode(t.fromId),i=e.getNode(t.toId);f(n),f(i),t.force_directed_spring=r.addSpring(n.force_directed_body,i.force_directed_body,-1,t.weight)},p=function(t){var n=t.force_directed_spring;if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&f(i),o&&f(o),t.force_directed_spring=null,delete t.force_directed_spring,r.removeSpring(n)}},v=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&l(n.node),n.link&&h(n.link)):"remove"===n.changeType&&(n.node&&d(n.node),n.link&&p(n.link))}},m=function(){e.forEachNode(l),e.forEachLink(h),e.addEventListener("changed",v)},g=function(e){return e?e.isPinned||e.data&&e.data.isPinned:!0},y=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;0!==e.getNodesCount()&&(e.forEachNode(function(e){var o=e.force_directed_body;o&&(g(e)&&o.loc(e.position),e.position.x=o.location.x,e.position.y=o.location.y,t>e.position.x&&(t=e.position.x),e.position.x>r&&(r=e.position.x),n>e.position.y&&(n=e.position.y),e.position.y>i&&(i=e.position.y))}),u.x1=t,u.x2=r,u.y1=n,u.y2=i)};return r.addSpringForce(o),r.addBodyForce(i),r.addBodyForce(a),m(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(20);return y(),n>e},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",v)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.position.xt.x2&&(t.x2=e.position.x),e.position.yt.y2&&(t.y2=e.position.y)},a=function(e){e.hasOwnProperty("position")||(e.position=i(e)),o(e,r)},u=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(a))},s=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&a(n.node)}};return{run:function(){this.step()},step:function(){return u(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",s)},placeNode:function(e){return"function"==typeof e?(i=e,u(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,c=t.container,f=!1,l=!0,d=0,h=0,p=!1,v=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){c=c||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:c}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x={x:0,y:0,node:null},w={x:0,y:0,node:null},V={x:0,y:0},b=Viva.Graph.Utils.events(window),E=Viva.Graph.Utils.events({}).extend(),G=function(t){var n=e.getNode(t.fromId),r=e.getNode(t.toId);n&&r&&(x.x=n.position.x,x.y=n.position.y,x.node=n,w.x=r.position.x,w.y=r.position.y,w.node=r,s.updateLinkPosition(t.ui,x,w))},P=function(e){V.x=e.position.x,V.y=e.position.y,s.updateNodePosition(e.ui,V)},N=function(){s.beginRender(),t.renderLinks&&!s.omitLinksRendering&&e.forEachLink(G),e.forEachNode(P),s.endRender()},_=function(){return p=u.step()&&!v,N(),!p},L=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return _()},n)):(d=0,h=0,i=Viva.Graph.Utils.timer(_,n)),void 0)},A=function(){p=!1,i.restart()},I=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},k=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(c);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),l=!1},T=function(e){var t=s.node(e);e.ui=t,s.initNode(t),P(e)},C=function(e){e.hasOwnProperty("ui")&&(s.releaseNode(e.ui),e.ui=null,delete e.ui)},M=function(e){var t=s.link(e);e.ui=t,s.initLink(t),s.omitLinksRendering||G(e)},S=function(e){e.hasOwnProperty("ui")&&(s.releaseLink(e.ui),e.ui=null,delete e.ui)},U=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=e.isPinned,e.isPinned=!0,v=!0,A()},onDrag:function(t,n){e.position.x+=n.x/g.scale,e.position.y+=n.y/g.scale,v=!0,N()},onStop:function(){e.isPinned=t,v=!1}})},R=function(e){r.bindDragNDrop(e,null)},D=function(){s.init(c),e.forEachNode(T),t.renderLinks&&e.forEachLink(M)},F=function(){s.release(c)},O=function(t){var n=t.node;"add"===t.changeType?(T(n),U(n),l&&k()):"remove"===t.changeType?(R(n),C(n),0===e.getNodesCount()&&(l=!0)):"update"===t.changeType&&(R(n),C(n),T(n),U(n))},z=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&M(n);else if("remove"===e.changeType)t.renderLinks&&S(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},B=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?O(n):n.link&&z(n);A()},Y=function(){k(),_()},X=function(){a&&(a.release(),a=null)},q=function(){o&&(o.stop("changed",B),o=null)},W=function(){b.on("resize",Y),X(),a=Viva.Graph.Utils.dragndrop(c),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),N()}),a.onScroll(function(e,t,n){var r=Math.pow(1.4,0>t?-.2:.2);g.scale=s.scale(r,n),N(),E.fire("scale",g.scale)}),e.forEachNode(U),q(),o=Viva.Graph.Utils.events(e),o.on("changed",B)},j=function(){f=!1,q(),X(),b.stop("resize",Y),E.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&S(e)}),e.forEachNode(function(e){R(e),C(e)}),u.dispose(),F()};return{run:function(e){return f||(y(),I(),k(),D(),W(),f=!0),L(e),this},reset:function(){s.resetScale(),k(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return N(),this},dispose:function(){j()},on:function(e,t){return E.addEventListener(e,t),this},off:function(e,t){return E.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var c=n(u.nodes[a]);if(!c.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(c.id,c.data)}for(a=0;u.links.length>a;++a){var f=o(u.links[a]);if(!f.hasOwnProperty("fromId")||!f.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(f.fromId,f.toId,f.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},c={},f=[t.id],l=function(e){c.hasOwnProperty(e.id)||(f.push(e.id),c[e.id]=i+1),c[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),c[t.id]=0,s[t.id]=1;f.length;)r=f.shift(),i=c[r],o=s[r],u.push(r),e.forEachLinkedNode(r,l,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},c=t.S;for(r=0;c.length>r;r+=1)s[c[r]]=0;for(;c.length;){for(i=c.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r); -return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},c=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},f=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},l=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},d=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?l(e):(l=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,d()},translateRel:function(e,r){t+=e,n+=r,d()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return c=e,this},placeLink:function(e){return f=e,this},init:function(t){e=t,d()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){c(e,t)},updateLinkPosition:function(e,t,n){f(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var c=r.childNodes[t];if(1===c.nodeType){var f=c.attr("class"),l=c.attr("id"),d=c.nodeName;if(a&&f){for(f=f.replace(/\s+/g," ").split(" "),n=0;f.length>n;n++)if(a&&f[n]===e.substr(1)){i.push(Viva.Graph.svg(c));break}}else{if(u&&l===e.substr(1)){i.push(Viva.Graph.svg(c));break}s&&d===e&&i.push(Viva.Graph.svg(c))}i=i.concat(Viva.Graph.svg(c).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i=1,o=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},a=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},u=function(){return Viva.Graph.svg("line").attr("stroke","#999")},s=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},c=function(e){e.fire("rescaled")},f=function(){if(e){var t="matrix("+i+", 0, 0,"+i+","+n+","+r+")";e.attr("transform",t)}},l={node:function(e){return e&&"function"!=typeof e?o(e):(o=e,this)},link:function(e){return e&&"function"!=typeof e?u(e):(u=e,this)},placeNode:function(e){return a=e,this},placeLink:function(e){return s=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,f()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(o,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(o).translate(-u.x,-u.y),f=e.getCTM().multiply(s);i=f.a,n=f.e,r=f.f;var l="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",l),c(this),i},resetScale:function(){i=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),c(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),f()},release:function(e){t&&e&&e.removeChild(t)},initLink:function(t){t&&(e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t))},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){a(e,t)},updateLinkPosition:function(e,t,n){s(e,t,n)},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(l).extend(),l},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),c=e.position,f=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,c.x,c.y)||r,l=n.intersectRect(c.x-s.w/2,c.y-s.h/2,c.x+s.w/2,c.y+s.h/2,c.x,c.y,r.x,r.y)||c;o+="M"+Math.round(f.x)+" "+Math.round(f.y)+"L"+Math.round(l.x)+" "+Math.round(l.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,c=4,f=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),d=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*f),p=new Float32Array(h),v=new Uint32Array(h),m=0,g=function(){if((m+1)*f>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(v),p=t,v=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(d,l),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;p[n*c]=t.x,p[n*c+1]=t.y,p[n*c+2]=e.size,v[n*c+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(v,e.id*c,m*c,c)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,c*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,c*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,c,f=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),p=0,v=new ArrayBuffer(16*l),m=new Float32Array(v),g=new Uint32Array(v),y=function(){if((p+1)*l>v.byteLength){var e=new ArrayBuffer(2*v.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,v=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,d),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*f;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),p+=1,o=e.id},removeLink:function(e){p>0&&(p-=1),p>e.id&&p>0&&r.copyArrayPart(g,e.id*f,p*f,f)},updateTransform:function(e){c=!0,s=e},updateSize:function(e,t){a=e,u=t,c=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,v,t.DYNAMIC_DRAW),c&&(c=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*p),o=p-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*f,o*f,f),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],c=[],f=function(e){return 0===(e&e-1)},l=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},d=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},p=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},v=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=d(e),o={offset:e};r.textureNumber>=s.length&&l();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),c[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!f(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=d(t.offset),r=d(o);v(r,n);var i=a[c[o]];return i.offset=t.offset,c[t.offset]=c[o],p(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){p(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,c,f=18,l=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),d=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,p=0,v=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(d,l),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*f;v[n]=t.x-e.size,v[n+1]=t.y-e.size,v[n+2]=4*e._offset,v[n+3]=t.x+e.size,v[n+4]=t.y-e.size,v[n+5]=4*e._offset+1,v[n+6]=t.x-e.size,v[n+7]=t.y+e.size,v[n+8]=4*e._offset+2,v[n+9]=t.x-e.size,v[n+10]=t.y+e.size,v[n+11]=4*e._offset+2,v[n+12]=t.x+e.size,v[n+13]=t.y-e.size,v[n+14]=4*e._offset+1,v[n+15]=t.x+e.size,v[n+16]=t.y+e.size,v[n+17]=4*e._offset+3},createNode:function(t){v=i.extendArray(v,p,f),p+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){p>0&&(p-=1),p>t.id&&p>0&&(t.src&&e.remove(t.src),i.copyArrayPart(v,t.id*f,p*f,f))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){c=!0,s=e},updateSize:function(e,t){a=e,u=t,c=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,v,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*p)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,c,f=0,l=0,d=[],h=[],p=Viva.Graph.View.webglLinkProgram(),v=Viva.Graph.View.webglNodeProgram(),m=function(){return Viva.Graph.View.webglSquare()},g=function(){return Viva.Graph.View.webglLine(3014898687)},y=function(){p.updateTransform(a),v.updateTransform(a)},x=function(){a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},w=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),p&&p.updateSize(i/2,o/2),v&&v.updateSize(i/2,o/2))},V=function(e){var t=f++,n=m(e);return n.id=t,v.createNode(n),d[t]=e,n},b=function(e){var t=l++,n=g(e);return n.id=t,p.createLink(n),h[t]=e,n},E=function(e){e.fire("rescaled")},G={node:function(e){return e&&"function"!=typeof e?V(e):(m=e,this)},link:function(e){return e&&"function"!=typeof e?b(e):(g=e,this)},placeNode:function(e){return u=e,this},placeLink:function(e){return s=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){l>0&&p.render(),f>0&&v.render()},bringLinkToFront:function(e){var t,n,r=p.getFrontLinkId();p.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].ui.id=r,h[t]=n,h[t].ui.id=t)},graphCenterChanged:function(){w()},initLink:function(){},initNode:function(){},translateRel:function(e,t){a[12]+=2*a[0]*e/i/a[0],a[13]-=2*a[5]*t/o/a[5],y()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=a[12],r-=a[13],a[12]+=n*(1-e),a[13]+=r*(1-e),a[0]*=e,a[5]*=e,y(),E(this),a[0]},resetScale:function(){return x(),r&&(w(),y()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),w(),x(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var s="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(s),s}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var f=e.clearColorValue;r.clearColor(f.r,f.g,f.b,f.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}p.load(r),p.updateSize(i/2,o/2),v.load(r),v.updateSize(i/2,o/2),y(),"function"==typeof c&&c(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){l>0&&(l-=1),p.removeLink(e);var t=e.id;if(l>t){if(0===l||l===t)return;h[t]=h[l],h[t].ui.id=t}},releaseNode:function(e){if(f>0&&(f-=1),v.removeNode(e),f>e.id){var t=e.id;if(0===f||f===t)return;var n=d[f],r=d[t];d[t]=n,d[t].ui.id=t,v.replaceProperties(r.ui,n.ui)}},updateNodePosition:function(e,t){t.y=-t.y,u&&u(e,t),v.position(e,t)},updateLinkPosition:function(e,t,n){t.y=-t.y,n.y=-n.y,s&&s(e,t,n),p.position(e,t,n)},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):c=e),n},setNodeProgram:function(e){if(!r&&e)v=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)p=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},getGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-a[12])/a[0],e.y=(e.y-a[13])/a[5],e.x*=i/2,e.y*=-o/2,e}};return Viva.Graph.Utils.events(G).extend(),G},Viva.Graph.webglInputEvents=function(e,t){if(e.webglInputEvents)return e.webglInputEvents;var n,r,i=function(e,t,n){if(e.ui&&e.ui.size){var r=e.position,i=e.ui.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},o=null,a=Viva.Graph.spatialIndex(t,i),u=[],s=[],c=[],f=[],l=[],d=[],h=[],p=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},m=function(e){return v(e),!1},g=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},y=function(t){var i={x:0,y:0},y=null,x=+new Date,w=function(e){g(l,[y,e]),i.x=e.clientX,i.y=e.clientY},V=function(){p.stop("mousemove",w),p.stop("mouseup",V)},b=function(){r=t.getBoundingClientRect()};window.addEventListener("resize",b),b(),t.addEventListener("mousemove",function(t){if(!o){var n,c=!1;i.x=t.clientX-r.left,i.y=t.clientY-r.top,e.getGraphCoordinates(i),n=a.getNodeAt(i.x,i.y),n&&y!==n?(y=n,c=c||g(u,[y])):null===n&&y!==n&&(c=c||g(s,[y]),y=null),c&&v(t)}}),t.addEventListener("mousedown",function(t){var o,u=!1;i.x=t.clientX-r.left,i.y=t.clientY-r.top,e.getGraphCoordinates(i),o=[a.getNodeAt(i.x,i.y),t],o[0]?(u=g(c,o),p.on("mousemove",w),p.on("mouseup",V),n=window.document.onselectstart,window.document.onselectstart=m,y=o[0]):y=null,u&&v(t)}),t.addEventListener("mouseup",function(t){var o,u=+new Date;i.x=t.clientX-r.left,i.y=t.clientY-r.top,e.getGraphCoordinates(i),o=[a.getNodeAt(i.x,i.y),t],o[0]&&(window.document.onselectstart=n,400>u-x&&o[0]===y?g(h,o):g(d,o),x=u,g(f,o)&&v(t))})};return e.getGraphicsRoot(y),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&u.push(e),this},mouseLeave:function(e){return"function"==typeof e&&s.push(e),this},mouseDown:function(e){return"function"==typeof e&&c.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&l.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&h.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t,e),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.ui.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.ui.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.ui.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.ui.id]=t}}}; \ No newline at end of file +var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.4.1",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){function e(){var e=4022871197,t=function(t){var n;for(t=""+t,n=0;t.length>n;n++){e+=t.charCodeAt(n);var r=.02519603282416938*e;e=r>>>0,r-=e,r*=e,e=r>>>0,r-=e,e+=4294967296*r}return 2.3283064365386963e-10*(e>>>0)};return t.version="Mash 0.9",t}function t(t){return function(t){var n,r,i=0,o=58,a=119,u=178,s=[],c=e();for(0===t.length&&(t=[+new Date]),n=0;256>n;n++)s[n]=c(" "),s[n]-=4.76837158203125e-7*c(" "),0>s[n]&&(s[n]+=1);for(r=0;t.length>r;r++)for(n=0;256>n;n++)s[n]-=c(t[r]),s[n]-=4.76837158203125e-7*c(t[r]),0>s[n]&&(s[n]+=1);c=null;var f=function(){var e;return i=255&i+1,o=255&o+1,a=255&a+1,u=255&u+1,e=s[i]-s[o],0>e&&(e+=1),e-=s[a],0>e&&(e+=1),e-=s[u],0>e&&(e+=1),s[i]=e,e};return f.uint32=function(){return 4294967296*f()>>>0},f.fract53=f,f.version="LFIB4 0.9",f.args=t,f}(t)}var n=new t(Array.prototype.slice.call(arguments));return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),c=Viva.Graph.Utils.events(e),f=Viva.Graph.Utils.findElementPosition,l=0,d=0,h=!1,p=0,v=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-l,y:r-d}),l=t,d=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},b=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(l=e.clientX,d=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:l,y:d}),s.on("mousemove",w),s.on("mouseup",V),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},V=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",V),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},E=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=v(t),o=f(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},N=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",E,!1):e.addEventListener("DOMMouseScroll",E,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",E,!1):e.removeEventListener("DOMMouseScroll",E,!1)),i=t},P=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=P(e.touches[0],e.touches[1]),r=0;p>n?r=-1:n>p&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),p=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),l=n.clientX,d=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:l,y:d}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),p=P(t.touches[0],t.touches[1])),void 0)};return c.on("mousedown",b),c.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",b),s.stop("mouseup",V),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),N(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.spatialIndex=function(e,t){var n,r,i=16;return"function"==typeof t?(r=t,n=function(t,n){var i=null;return e.forEachNode(function(e){return r(e,t,n)?(i=e,!0):void 0}),i}):"number"==typeof t&&(i=t,n=function(t,n){var r=null;return e.forEachNode(function(e){var o=e.position;return t>o.x-i&&o.x+i>t&&n>o.y-i&&o.y+i>n?(r=e,!0):void 0}),r}),{getNodeAt:n}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,c,f,l,d,h,p,v,m,g,y,x,w,b={x:0,y:0};return s=r-t,f=e-n,d=n*t-e*r,m=s*i+f*o+d,g=s*a+f*u+d,0!==m&&0!==g&&m>=0==g>=4?null:(c=u-o,l=i-a,h=a*o-i*u,p=c*e+l*t+h,v=c*n+l*r+h,0!==p&&0!==v&&p>=0==v>=0?null:(y=s*l-c*f,0===y?null:(x=0>y?-y/2:y/2,x=0,w=f*h-l*d,b.x=(0>w?w-x:w+x)/y,w=c*d-s*h,b.y=(0>w?w-x:w+x)/y,b)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,c=a.y-e.y,f=s*s+c*c;for(r=1;o.length>r;++r){a=o[r];var l=i(a);l===u?(s=a.x-e.x,c=a.y-e.y,n=s*s+c*c,f>n?o.splice(r,1):o.splice(r-1,1)):u=l}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},c=function(e,t){o.push({node:e,changeType:t})},f=function(e,t){o.push({link:e,changeType:t})},l=function(e){return e&&"object"==typeof e&&"number"==typeof e.length&&"function"==typeof e.splice&&!e.propertyIsEnumerable("length")},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);if(i?c(i,"update"):(i=new Viva.Graph.Node(t),r++,c(i,"add")),n){var o,a=i.data||{},f=typeof n;if("string"===f||l(n)||"number"===f||"boolean"===f)a=n;else if("undefined"===f)a=null;else for(o in n)n.hasOwnProperty(o)&&(a[o]=n[o]);i.data=a}return e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),c=""+e+(""+r),l=n.hasOwnProperty(c);(l||this.hasLink(e,r))&&(l||(n[c]=0),c+="@"+ ++n[c]);var d=new Viva.Graph.Link(e,r,i,c);return t.push(d),o.links.push(d),a.links.push(d),f(d,"add"),s(this),d},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),f(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,c(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n;if("function"==typeof e)for(n=0;t.length>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var c=u.velocity.x,f=u.velocity.y,l=Math.sqrt(c*c+f*f);l>r&&(u.velocity.x=r*c/l,u.velocity.y=r*f/l),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},c=[],f=0,l=function(){var e;return c[f]?(e=c[f],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,c[f]=e),++f,e},d=l(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return.01>n&&.01>r},p=function(e){for(o.reset(),o.push(d,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,c=n.left,f=(n.right+c)/2,p=n.top,v=(n.bottom+p)/2;if(i>f){s+=1;var m=c;c=f,f+=f-m}if(a>v){s+=2;var g=p;p=v,v+=v-g}var y=n.quads[s];y||(y=l(),y.left=c,y.top=p,y.right=f,y.bottom=v,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){var w,b;do{var V=2*u.nextDouble()*Math.PI,E=.006*(n.right-n.left)*Math.cos(V),N=.006*(n.bottom-n.top)*Math.sin(V);w=x.location.x+E,b=x.location.y+N}while(n.left>w||w>n.right||n.top>b||b>n.bottom);x.location.x=w,x.location.y=b}o.push(n,x),o.push(n,r)}else n.body=r}},v=function(e){var t,n,o,s,c=i,f=1,l=0,h=1;for(c[0]=d;f;){var p=c[l],v=p.body;f-=1,l+=1,v&&v!==e?(n=v.location.x-e.location.x,o=v.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=p.massX/p.mass-e.location.x,o=p.massY/p.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(p.right-p.left)/s?(t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(p.quads[0]&&(c[h]=p.quads[0],f+=1,h+=1),p.quads[1]&&(c[h]=p.quads[1],f+=1,h+=1),p.quads[2]&&(c[h]=p.quads[2],f+=1,h+=1),p.quads[3]&&(c[h]=p.quads[3],f+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,c=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>c&&(r=c),c>o&&(o=c)}var h=i-n,v=o-r;for(h>v?o=r+h:i=n+v,f=0,d=l(),d.left=n,d.right=i,d.top=r,d.bottom=o,t=u;t--;)p(a[t],d)};return{insert:p,init:m,update:v,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{init:function(){},update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{init:function(){},update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var c=s-o,f=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*c/s*n.weight;r.force.x+=f*a,r.force.y+=f*u,i.force.x+=-f*a,i.force.y+=-f*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t=e,n=[],r=[],i=[],o=[];return{speedLimit:1,bodies:n,accumulate:function(){var e,t,a;for(e=i.length;e--;)i[e].init(this);for(e=o.length;e--;)o[e].init(this);for(e=n.length;e--;)for(a=n[e],a.force.x=0,a.force.y=0,t=0;i.length>t;t++)i[t].update(a);for(e=0;r.length>e;++e)for(t=0;o.length>t;t++)o[t].update(r[e])},run:function(e){return this.accumulate(),t.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return n.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,n);return 0>t?!1:n.splice(t,1)},addSpring:function(e,t,n,i,o){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};o="number"==typeof o?o:1;var a=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,o);return r.push(a),a},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,r);return 0>t?!1:r.splice(t,1)},addBodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};i.push(e)},addSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};o.push(e)}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{compatible:!1,springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),c=function(n){var r=(u.x1+u.x2)/2,i=(u.y1+u.y2)/2,o=t.springLength;if(n.links&&n.links.length>0){var a=n.links[0],c=a.fromId!==n.id?e.getNode(a.fromId):e.getNode(a.toId);c.position&&(r=c.position.x,i=c.position.y)}return{x:r+s.next(o)-o/2,y:i+s.next(o)-o/2}},f={},l=function(e){return f[e]},d=function(e){f[e.id]=null,delete f[e.id]},h={},p=function(t){var n=l(t.id);n.mass=1+e.getLinks(t.id).length/3},v=function(e){var n=l(e.id);if(!n){n=new Viva.Graph.Physics.Body,f[e.id]=n;var i=c(n);n.loc(i),p(e),t.compatible&&(e.position=i,e.force_directed_body=n),r.addBody(n)}},m=function(e){var n=l(e.id);n&&(t.compatible&&(e.force_directed_body=null,delete e.force_directed_body),d(e),r.removeBody(n))},g=function(n){var i=e.getNode(n.fromId),o=e.getNode(n.toId);p(i),p(o);var a=l(n.fromId),u=l(n.toId),s=r.addSpring(a,u,-1,n.weight);h[n.id]=s,t.compatible&&(n.force_directed_spring=s)},y=function(n){var i=h[n.id];if(i){var o=e.getNode(n.fromId),a=e.getNode(n.toId);o&&p(o),a&&p(a),t.compatible&&(n.force_directed_spring=null,delete n.force_directed_spring),delete h[n.id],r.removeSpring(i)}},x=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&v(n.node),n.link&&g(n.link)):"remove"===n.changeType&&(n.node&&m(n.node),n.link&&y(n.link))}},w=function(){e.forEachNode(v),e.forEachLink(g),e.addEventListener("changed",x)},b=function(e,t){return e||t?e&&(e.isPinned||e.data&&e.data.isPinned)||t&&t.isPinned:!0},V=function(){var n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var a in f)if(f.hasOwnProperty(a)){var s=f[a];b(null,s)?(s.location.x=s.prevLocation.x,s.location.y=s.prevLocation.y):(s.prevLocation.x=s.location.x,s.prevLocation.y=s.location.y),n>s.location.x&&(n=s.location.x),s.location.x>i&&(i=s.location.x),r>s.location.y&&(r=s.location.y),s.location.y>o&&(o=s.location.y)}t.compatible&&e.forEachNode(function(e){var t=e.force_directed_body;t&&(e.position.x=t.location.x,e.position.y=t.location.y)}),u.x1=n,u.x2=i,u.y1=r,u.y2=o}};return r.addSpringForce(o),r.addBodyForce(i),r.addBodyForce(a),w(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(20);return V(),n>e},isNodePinned:function(e){var t=l(e.id);return b(e,t)},pinNode:function(e,t){var n=l(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=l(e);return t&&t.location},setNodePosition:function(e,t,n){var r=l(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",x)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.position.xt.x2&&(t.x2=e.position.x),e.position.yt.y2&&(t.y2=e.position.y)},a=function(e){e.hasOwnProperty("position")||(e.position=i(e)),o(e,r)},u=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(a))},s=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&a(n.node)}};return{run:function(){this.step()},step:function(){return u(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",s)},placeNode:function(e){return"function"==typeof e?(i=e,u(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,c=t.container,f=!1,l=!0,d=0,h=0,p=!1,v=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){c=c||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:c}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.compatible=t.compatible||!1,t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x={x:0,y:0,node:null},w={x:0,y:0,node:null},b={x:0,y:0},V=Viva.Graph.Utils.events(window),E=Viva.Graph.Utils.events({}).extend(),N=function(e){var t=u.getNodePosition(e.fromId),n=u.getNodePosition(e.toId);t&&n&&(x.x=t.x,x.y=t.y,w.x=n.x,w.y=n.y,s.updateLinkPosition(e,x,w))},P=function(e){var t=u.getNodePosition(e.id);b.x=t.x,b.y=t.y,s.updateNodePosition(e,b)},G=function(){s.beginRender(),t.renderLinks&&!s.omitLinksRendering&&e.forEachLink(N),e.forEachNode(P),s.endRender()},L=function(){return p=u.step()&&!v,G(),!p},_=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return L()},n)):(d=0,h=0,i=Viva.Graph.Utils.timer(L,n)),void 0)},A=function(){p=!1,i.restart()},I=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},k=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(c);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),l=!1},T=function(e){var n=s.addNode(e);t.compatible&&(e.ui=n),P(e)},C=function(e){s.releaseNode(e),t.compatible&&e.hasOwnProperty("ui")&&(e.ui=null,delete e.ui)},M=function(e){var n=s.addLink(e);t.compatible&&(e.ui=n),s.omitLinksRendering||N(e)},S=function(e){s.releaseLink(e),t.compatible&&e.hasOwnProperty("ui")&&(e.ui=null,delete e.ui)},U=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),v=!0,A()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),v=!0,G()},onStop:function(){u.pinNode(e,t),v=!1}})},R=function(e){r.bindDragNDrop(e,null)},D=function(){s.init(c),e.forEachNode(T),t.renderLinks&&e.forEachLink(M)},F=function(){s.release(c)},O=function(t){var n=t.node;"add"===t.changeType?(T(n),U(n),l&&k()):"remove"===t.changeType?(R(n),C(n),0===e.getNodesCount()&&(l=!0)):"update"===t.changeType&&(R(n),C(n),T(n),U(n))},z=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&M(n);else if("remove"===e.changeType)t.renderLinks&&S(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},B=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?O(n):n.link&&z(n);A()},Y=function(){k(),L()},X=function(){a&&(a.release(),a=null)},q=function(){o&&(o.stop("changed",B),o=null)},W=function(){V.on("resize",Y),X(),a=Viva.Graph.Utils.dragndrop(c),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),G()}),a.onScroll(function(e,t,n){var r=Math.pow(1.4,0>t?-.2:.2);g.scale=s.scale(r,n),G(),E.fire("scale",g.scale)}),e.forEachNode(U),q(),o=Viva.Graph.Utils.events(e),o.on("changed",B)},j=function(){f=!1,q(),X(),V.stop("resize",Y),E.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&S(e)}),e.forEachNode(function(e){R(e),C(e)}),u.dispose(),F()};return{run:function(e){return f||(y(),I(),k(),D(),W(),f=!0),_(e),this},reset:function(){s.resetScale(),k(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return G(),this},dispose:function(){j()},on:function(e,t){return E.addEventListener(e,t),this},off:function(e,t){return E.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var c=n(u.nodes[a]);if(!c.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(c.id,c.data)}for(a=0;u.links.length>a;++a){var f=o(u.links[a]);if(!f.hasOwnProperty("fromId")||!f.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(f.fromId,f.toId,f.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},c={},f=[t.id],l=function(e){c.hasOwnProperty(e.id)||(f.push(e.id),c[e.id]=i+1),c[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),c[t.id]=0,s[t.id]=1;f.length;)r=f.shift(),i=c[r],o=s[r],u.push(r),e.forEachLinkedNode(r,l,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},c=t.S;for(r=0;c.length>r;r+=1)s[c[r]]=0;for(;c.length;){for(i=c.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1; +return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},c=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},f=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},l=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},d=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?l(e):(l=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,d()},translateRel:function(e,r){t+=e,n+=r,d()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return c=e,this},placeLink:function(e){return f=e,this},init:function(t){e=t,d()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){c(e,t)},updateLinkPosition:function(e,t,n){f(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var c=r.childNodes[t];if(1===c.nodeType){var f=c.attr("class"),l=c.attr("id"),d=c.nodeName;if(a&&f){for(f=f.replace(/\s+/g," ").split(" "),n=0;f.length>n;n++)if(a&&f[n]===e.substr(1)){i.push(Viva.Graph.svg(c));break}}else{if(u&&l===e.substr(1)){i.push(Viva.Graph.svg(c));break}s&&d===e&&i.push(Viva.Graph.svg(c))}i=i.concat(Viva.Graph.svg(c).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i=1,o={},a={},u=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},s=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},c=function(){return Viva.Graph.svg("line").attr("stroke","#999")},f=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},l=function(e){e.fire("rescaled")},d=function(){if(e){var t="matrix("+i+", 0, 0,"+i+","+n+","+r+")";e.attr("transform",t)}},h={getNodeUI:function(e){return o[e]},getLinkUI:function(e){return a[e]},node:function(e){return"function"==typeof e?(u=e,this):void 0},link:function(e){return"function"==typeof e?(c=e,this):void 0},placeNode:function(e){return s=e,this},placeLink:function(e){return f=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,d()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(o,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(o).translate(-u.x,-u.y),c=e.getCTM().multiply(s);i=c.a,n=c.e,r=c.f;var f="matrix("+c.a+", 0, 0,"+c.d+","+c.e+","+c.f+")";return e.attr("transform",f),l(this),i},resetScale:function(){i=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),l(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),d()},release:function(e){t&&e&&e.removeChild(t)},addLink:function(t){var n=c(t);if(n)return a[t.id]=n,e.childElementCount>0?e.insertBefore(n,e.firstChild):e.appendChild(n),n},releaseLink:function(t){var n=this.getLinkUI(t);e.removeChild(n)},addNode:function(t){var n=u(t);if(n)return o[t.id]=n,e.appendChild(n),n},releaseNode:function(t){var n=this.getNodeUI(t.id);n&&e.removeChild(n)},updateNodePosition:function(e,t){var n=this.getNodeUI(e.id);n&&s(n,t,e)},updateLinkPosition:function(e,t,n){var r=this.getLinkUI(e.id);f(r,t,n,e)},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(h).extend(),h},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),c=e.position,f=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,c.x,c.y)||r,l=n.intersectRect(c.x-s.w/2,c.y-s.h/2,c.x+s.w/2,c.y+s.h/2,c.x,c.y,r.x,r.y)||c;o+="M"+Math.round(f.x)+" "+Math.round(f.y)+"L"+Math.round(l.x)+" "+Math.round(l.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,c=4,f=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),d=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*f),p=new Float32Array(h),v=new Uint32Array(h),m=0,g=function(){if((m+1)*f>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(v),p=t,v=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(d,l),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;p[n*c]=t.x,p[n*c+1]=t.y,p[n*c+2]=e.size,v[n*c+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(v,e.id*c,m*c,c)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,c*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,c*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,c,f=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),p=0,v=new ArrayBuffer(16*l),m=new Float32Array(v),g=new Uint32Array(v),y=function(){if((p+1)*l>v.byteLength){var e=new ArrayBuffer(2*v.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,v=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,d),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*f;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),p+=1,o=e.id},removeLink:function(e){p>0&&(p-=1),p>e.id&&p>0&&r.copyArrayPart(g,e.id*f,p*f,f)},updateTransform:function(e){c=!0,s=e},updateSize:function(e,t){a=e,u=t,c=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,v,t.DYNAMIC_DRAW),c&&(c=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*p),o=p-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*f,o*f,f),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],c=[],f=function(e){return 0===(e&e-1)},l=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},d=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},p=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},v=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=d(e),o={offset:e};r.textureNumber>=s.length&&l();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),c[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!f(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=d(t.offset),r=d(o);v(r,n);var i=a[c[o]];return i.offset=t.offset,c[t.offset]=c[o],p(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){p(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,c,f=18,l=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),d=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,p=0,v=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(d,l),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*f;v[n]=t.x-e.size,v[n+1]=t.y-e.size,v[n+2]=4*e._offset,v[n+3]=t.x+e.size,v[n+4]=t.y-e.size,v[n+5]=4*e._offset+1,v[n+6]=t.x-e.size,v[n+7]=t.y+e.size,v[n+8]=4*e._offset+2,v[n+9]=t.x-e.size,v[n+10]=t.y+e.size,v[n+11]=4*e._offset+2,v[n+12]=t.x+e.size,v[n+13]=t.y-e.size,v[n+14]=4*e._offset+1,v[n+15]=t.x+e.size,v[n+16]=t.y+e.size,v[n+17]=4*e._offset+3},createNode:function(t){v=i.extendArray(v,p,f),p+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){p>0&&(p-=1),p>t.id&&p>0&&(t.src&&e.remove(t.src),i.copyArrayPart(v,t.id*f,p*f,f))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){c=!0,s=e},updateSize:function(e,t){a=e,u=t,c=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,v,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*p)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,c,f=0,l=0,d=[],h=[],p=Viva.Graph.View.webglLinkProgram(),v=Viva.Graph.View.webglNodeProgram(),m=function(){return Viva.Graph.View.webglSquare()},g=function(){return Viva.Graph.View.webglLine(3014898687)},y=function(){p.updateTransform(a),v.updateTransform(a)},x=function(){a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},w=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),p&&p.updateSize(i/2,o/2),v&&v.updateSize(i/2,o/2))},b=function(e){var t=f++,n=m(e);return n.id=t,v.createNode(n),d[t]=e,n},V=function(e){var t=l++,n=g(e);return n.id=t,p.createLink(n),h[t]=e,n},E=function(e){e.fire("rescaled")},N={node:function(e){return e&&"function"!=typeof e?b(e):(m=e,this)},link:function(e){return e&&"function"!=typeof e?V(e):(g=e,this)},placeNode:function(e){return u=e,this},placeLink:function(e){return s=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){l>0&&p.render(),f>0&&v.render()},bringLinkToFront:function(e){var t,n,r=p.getFrontLinkId();p.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].ui.id=r,h[t]=n,h[t].ui.id=t)},graphCenterChanged:function(){w()},initLink:function(){},initNode:function(){},translateRel:function(e,t){a[12]+=2*a[0]*e/i/a[0],a[13]-=2*a[5]*t/o/a[5],y()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=a[12],r-=a[13],a[12]+=n*(1-e),a[13]+=r*(1-e),a[0]*=e,a[5]*=e,y(),E(this),a[0]},resetScale:function(){return x(),r&&(w(),y()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),w(),x(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var s="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(s),s}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var f=e.clearColorValue;r.clearColor(f.r,f.g,f.b,f.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}p.load(r),p.updateSize(i/2,o/2),v.load(r),v.updateSize(i/2,o/2),y(),"function"==typeof c&&c(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){l>0&&(l-=1),p.removeLink(e);var t=e.id;if(l>t){if(0===l||l===t)return;h[t]=h[l],h[t].ui.id=t}},releaseNode:function(e){if(f>0&&(f-=1),v.removeNode(e),f>e.id){var t=e.id;if(0===f||f===t)return;var n=d[f],r=d[t];d[t]=n,d[t].ui.id=t,v.replaceProperties(r.ui,n.ui)}},updateNodePosition:function(e,t){t.y=-t.y,u&&u(e,t),v.position(e,t)},updateLinkPosition:function(e,t,n){t.y=-t.y,n.y=-n.y,s&&s(e,t,n),p.position(e,t,n)},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):c=e),n},setNodeProgram:function(e){if(!r&&e)v=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)p=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},getGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-a[12])/a[0],e.y=(e.y-a[13])/a[5],e.x*=i/2,e.y*=-o/2,e}};return Viva.Graph.Utils.events(N).extend(),N},Viva.Graph.webglInputEvents=function(e,t){if(e.webglInputEvents)return e.webglInputEvents;var n,r,i=function(e,t,n){if(e.ui&&e.ui.size){var r=e.position,i=e.ui.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},o=null,a=Viva.Graph.spatialIndex(t,i),u=[],s=[],c=[],f=[],l=[],d=[],h=[],p=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},m=function(e){return v(e),!1},g=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},y=function(t){var i={x:0,y:0},y=null,x=+new Date,w=function(e){g(l,[y,e]),i.x=e.clientX,i.y=e.clientY},b=function(){p.stop("mousemove",w),p.stop("mouseup",b)},V=function(){r=t.getBoundingClientRect()};window.addEventListener("resize",V),V(),t.addEventListener("mousemove",function(t){if(!o){var n,c=!1;i.x=t.clientX-r.left,i.y=t.clientY-r.top,e.getGraphCoordinates(i),n=a.getNodeAt(i.x,i.y),n&&y!==n?(y=n,c=c||g(u,[y])):null===n&&y!==n&&(c=c||g(s,[y]),y=null),c&&v(t)}}),t.addEventListener("mousedown",function(t){var o,u=!1;i.x=t.clientX-r.left,i.y=t.clientY-r.top,e.getGraphCoordinates(i),o=[a.getNodeAt(i.x,i.y),t],o[0]?(u=g(c,o),p.on("mousemove",w),p.on("mouseup",b),n=window.document.onselectstart,window.document.onselectstart=m,y=o[0]):y=null,u&&v(t)}),t.addEventListener("mouseup",function(t){var o,u=+new Date;i.x=t.clientX-r.left,i.y=t.clientY-r.top,e.getGraphCoordinates(i),o=[a.getNodeAt(i.x,i.y),t],o[0]&&(window.document.onselectstart=n,400>u-x&&o[0]===y?g(h,o):g(d,o),x=u,g(f,o)&&v(t))})};return e.getGraphicsRoot(y),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&u.push(e),this},mouseLeave:function(e){return"function"==typeof e&&s.push(e),this},mouseDown:function(e){return"function"==typeof e&&c.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&l.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&h.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t,e),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.ui.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.ui.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.ui.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.ui.id]=t}}}; \ No newline at end of file diff --git a/src/Core/graph.js b/src/Core/graph.js index 9cba92c..ba49f5b 100644 --- a/src/Core/graph.js +++ b/src/Core/graph.js @@ -24,6 +24,8 @@ Viva.Graph.graph = function () { var nodes = {}, links = [], + // Hash of multi-edges. Used to track ids of edges between same nodes + multiEdges = {}, nodesCount = 0, suspendEvents = 0, @@ -146,7 +148,16 @@ Viva.Graph.graph = function () { var fromNode = this.getNode(fromId) || this.addNode(fromId); var toNode = this.getNode(toId) || this.addNode(toId); - var link = new Viva.Graph.Link(fromId, toId, data); + var linkId = fromId.toString() + toId.toString(); + var isMultiEdge = multiEdges.hasOwnProperty(linkId); + if (isMultiEdge || this.hasLink(fromId, toId)) { + if (!isMultiEdge) { + multiEdges[linkId] = 0; + } + linkId += '@' + (++multiEdges[linkId]); + } + + var link = new Viva.Graph.Link(fromId, toId, data, linkId); links.push(link); @@ -403,4 +414,4 @@ Viva.Graph.graph = function () { Viva.Graph.Utils.events(graphPart).extend(); return graphPart; -}; \ No newline at end of file +}; diff --git a/src/Core/primitives.js b/src/Core/primitives.js index b094147..192250b 100644 --- a/src/Core/primitives.js +++ b/src/Core/primitives.js @@ -28,8 +28,9 @@ Viva.Graph.Node = function (id) { /** * Internal structure to represent links; */ -Viva.Graph.Link = function (fromId, toId, data) { +Viva.Graph.Link = function (fromId, toId, data, id) { this.fromId = fromId; this.toId = toId; this.data = data; -}; \ No newline at end of file + this.id = id; +}; diff --git a/src/Input/domInputManager.js b/src/Input/domInputManager.js index bbbe21e..18f6dc6 100644 --- a/src/Input/domInputManager.js +++ b/src/Input/domInputManager.js @@ -3,7 +3,8 @@ */ Viva.Input = Viva.Input || {}; -Viva.Input.domInputManager = function () { +Viva.Input.domInputManager = function (graph, graphics) { + var nodeEvents = {}; return { /** * Called by renderer to listen to drag-n-drop events from node. E.g. for CSS/SVG @@ -17,8 +18,10 @@ Viva.Input.domInputManager = function () { * onStop: function() */ bindDragNDrop : function (node, handlers) { + var events; if (handlers) { - var events = Viva.Graph.Utils.dragndrop(node.ui); + var nodeUI = graphics.getNodeUI(node.id); + events = Viva.Graph.Utils.dragndrop(nodeUI); if (typeof handlers.onStart === 'function') { events.onStart(handlers.onStart); } @@ -29,12 +32,10 @@ Viva.Input.domInputManager = function () { events.onStop(handlers.onStop); } - node.events = events; - } else if (node.events) { - // TODO: i'm not sure if this is required in JS world... - node.events.release(); - node.events = null; - delete node.events; + nodeEvents[node.id] = events; + } else if (( events = nodeEvents[node.id] )) { + events.release(); + delete nodeEvents[node.id]; } } }; diff --git a/src/Layout/forceDirected.js b/src/Layout/forceDirected.js index 3d73e13..4c1a408 100644 --- a/src/Layout/forceDirected.js +++ b/src/Layout/forceDirected.js @@ -13,6 +13,12 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { } settings = Viva.lazyExtend(settings, { + /** + * If true, the layout API will be compatible with + * old version of the library, where each node had it's own + * position property. This was a bad API decision... + */ + compatible: false, /** * Ideal length for links (springs in physical model). */ @@ -59,10 +65,10 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { graphRect = new Viva.Graph.Rect(), random = Viva.random('ted.com', 103, 114, 101, 97, 116), - getBestNodePosition = function(node) { + getBestBodyPosition = function(node) { // TODO: Initial position could be picked better, e.g. take into // account all neighbouring nodes/links, not only one. - // TODO: this is the same as in gem layout. consider refactoring. + // How about center of mass? var baseX = (graphRect.x1 + graphRect.x2) / 2, baseY = (graphRect.y1 + graphRect.y2) / 2, springLength = settings.springLength; @@ -82,61 +88,94 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { }; }, - updateNodeMass = function(node) { - var body = node.force_directed_body; + nodeBodies = {}, + getBody = function (nodeId) { + return nodeBodies[nodeId]; + }, + + releaseBody = function (node) { + nodeBodies[node.id] = null; + delete nodeBodies[node.id]; + }, + + springs = {}, + + updateBodyMass = function(node) { + var body = getBody(node.id); body.mass = 1 + graph.getLinks(node.id).length / 3.0; }, initNode = function(node) { - var body = node.force_directed_body; + var body = getBody(node.id); if (!body) { - // TODO: rename position to location or location to position to be consistent with - // other places. - node.position = node.position || getBestNodePosition(node); - body = new Viva.Graph.Physics.Body(); - node.force_directed_body = body; - updateNodeMass(node); + nodeBodies[node.id] = body; + var position = getBestBodyPosition(body); + body.loc(position); + updateBodyMass(node); + + if (settings.compatible) { + // This is depricated method. Please never ever use + // 'compatible' mode: it has a curse of shared data store + // i.e. there is no way two layouters could layout the same + // graph, since they both would compete for positions + node.position = position; + node.force_directed_body = body; + } - body.loc(node.position); forceSimulator.addBody(body); } }, releaseNode = function(node) { - var body = node.force_directed_body; + var body = getBody(node.id); if (body) { - node.force_directed_body = null; - delete node.force_directed_body; + if (settings.compatible) { + node.force_directed_body = null; + delete node.force_directed_body; + } + releaseBody(node); forceSimulator.removeBody(body); } }, initLink = function(link) { - // TODO: what if bodies are not initialized? var from = graph.getNode(link.fromId), to = graph.getNode(link.toId); - updateNodeMass(from); - updateNodeMass(to); - link.force_directed_spring = forceSimulator.addSpring(from.force_directed_body, to.force_directed_body, -1.0, link.weight); + updateBodyMass(from); + updateBodyMass(to); + + var fromBody = getBody(link.fromId), + toBody = getBody(link.toId), + spring = forceSimulator.addSpring(fromBody, toBody, -1.0, link.weight); + + // TODO: this has a bug, with multiple springs between same nodes + springs[link.id] = spring; + + if (settings.compatible) { + // bad... + link.force_directed_spring = spring; + } }, releaseLink = function(link) { - var spring = link.force_directed_spring; + var spring = springs[link.id]; if (spring) { var from = graph.getNode(link.fromId), to = graph.getNode(link.toId); if (from) { - updateNodeMass(from); + updateBodyMass(from); } if (to) { - updateNodeMass(to); + updateBodyMass(to); } - - link.force_directed_spring = null; - delete link.force_directed_spring; + if (settings.compatible) { + link.force_directed_spring = null; + delete link.force_directed_spring; + } + delete springs[link.id]; forceSimulator.removeSpring(spring); } @@ -169,12 +208,14 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { graph.addEventListener('changed', onGraphChanged); }, - isNodePinned = function(node) { - if (!node) { + isNodePinned = function(node, body) { + // this potentiall should make it easy to refactor when compatible mode goes away + if (!node && !body) { return true; } - return node.isPinned || (node.data && node.data.isPinned); + return (node && (node.isPinned || (node.data && node.data.isPinned))) || + (body && body.isPinned); }, updateNodePositions = function() { @@ -182,39 +223,54 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { y1 = Number.MAX_VALUE, x2 = Number.MIN_VALUE, y2 = Number.MIN_VALUE; + if (graph.getNodesCount() === 0) { return; } - - graph.forEachNode(function(node) { - var body = node.force_directed_body; - if (!body) { - // This could be a sign someone removed the propery. - // I should really decouple force related stuff from node - return; + for (var key in nodeBodies) { + if (nodeBodies.hasOwnProperty(key)) { + // how about pinned nodes? + var body = nodeBodies[key]; + if (isNodePinned(null, body)) { + body.location.x = body.prevLocation.x; + body.location.y = body.prevLocation.y; + } else { + body.prevLocation.x = body.location.x; + body.prevLocation.y = body.location.y; + } + if (body.location.x < x1) { + x1 = body.location.x; + } + if (body.location.x > x2) { + x2 = body.location.x; + } + if (body.location.y < y1) { + y1 = body.location.y; + } + if (body.location.y > y2) { + y2 = body.location.y; + } } + } - if (isNodePinned(node)) { - body.loc(node.position); - } + if (settings.compatible) { + graph.forEachNode(function(node) { + var body = node.force_directed_body; + if (!body) { + // This could be a sign someone removed the propery. + // Please don't use 'compatible' mode + return; + } - // TODO: once again: use one name to be consistent (position vs location) - node.position.x = body.location.x; - node.position.y = body.location.y; + // if (isNodePinned(node)) { + // body.loc(node.position); + // } - if (node.position.x < x1) { - x1 = node.position.x; - } - if (node.position.x > x2) { - x2 = node.position.x; - } - if (node.position.y < y1) { - y1 = node.position.y; - } - if (node.position.y > y2) { - y2 = node.position.y; - } - }); + node.position.x = body.location.x; + node.position.y = body.location.y; + + }); + } graphRect.x1 = x1; graphRect.x2 = x2; @@ -250,6 +306,29 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { return energy < STABLE_THRESHOLD; }, + isNodePinned: function (node) { + var body = getBody(node.id); + return isNodePinned(node, body); + }, + + pinNode: function (node, isPinned) { + var body = getBody(node.id); + body.isPinned = !!isPinned; + }, + + getNodePosition: function (nodeId) { + var body = getBody(nodeId); + return body && body.location; + }, + + setNodePosition: function (node, x, y) { + var body = getBody(node.id); + if (body) { + body.prevLocation.x = body.location.x = x; + body.prevLocation.y = body.location.y = y; + } + }, + /** * Returns rectangle structure {x1, y1, x2, y2}, which represents * current space occupied by graph. diff --git a/src/View/renderer.js b/src/View/renderer.js index 5689f4b..1d2514a 100644 --- a/src/View/renderer.js +++ b/src/View/renderer.js @@ -37,7 +37,13 @@ Viva.Graph.View = Viva.Graph.View || {}; * // Number of layout iterations to run before displaying the graph. The bigger you set this number * // the closer to ideal position graph will apper first time. But be careful: for large graphs * // it can freeze the browser. - * prerender : 0 + * prerender : 0, + * + * // Renderer should be compatible with older version of VivaGraph. + * // Warning: This option will be depricated soon. Compatible mode has a flaw of data being + * // shared on a node object of a graph. Which makes it impossible to reuse between multiple + * // renderers/layouters. + * compatible: false * } */ Viva.Graph.View.renderer = function (graph, settings) { @@ -80,6 +86,7 @@ Viva.Graph.View.renderer = function (graph, settings) { settings.renderLinks = true; } + settings.compatible = settings.compatible || false; settings.prerender = settings.prerender || 0; inputManager = (graphics.inputManager || Viva.Input.domInputManager)(graph, graphics); }, @@ -94,29 +101,28 @@ Viva.Graph.View.renderer = function (graph, settings) { renderLink = function (link) { - var fromNode = graph.getNode(link.fromId), - toNode = graph.getNode(link.toId); + var fromNode = layout.getNodePosition(link.fromId), + toNode = layout.getNodePosition(link.toId); if (!fromNode || !toNode) { return; } - cachedFromPos.x = fromNode.position.x; - cachedFromPos.y = fromNode.position.y; - cachedFromPos.node = fromNode; + cachedFromPos.x = fromNode.x; + cachedFromPos.y = fromNode.y; - cachedToPos.x = toNode.position.x; - cachedToPos.y = toNode.position.y; - cachedToPos.node = toNode; + cachedToPos.x = toNode.x; + cachedToPos.y = toNode.y; - graphics.updateLinkPosition(link.ui, cachedFromPos, cachedToPos); + graphics.updateLinkPosition(link, cachedFromPos, cachedToPos); }, renderNode = function (node) { - cachedNodePos.x = node.position.x; - cachedNodePos.y = node.position.y; + var pos = layout.getNodePosition(node.id); + cachedNodePos.x = pos.x; + cachedNodePos.y = pos.y; - graphics.updateNodePosition(node.ui, cachedNodePos); + graphics.updateNodePosition(node, cachedNodePos); }, renderGraph = function () { @@ -184,26 +190,27 @@ Viva.Graph.View.renderer = function (graph, settings) { }, createNodeUi = function (node) { - var nodeUI = graphics.node(node); - node.ui = nodeUI; - graphics.initNode(nodeUI); + var nodeUI = graphics.addNode(node); + if (settings.compatible) { + node.ui = nodeUI; + } renderNode(node); }, removeNodeUi = function (node) { - if (node.hasOwnProperty('ui')) { - graphics.releaseNode(node.ui); - + graphics.releaseNode(node); + if (settings.compatible && node.hasOwnProperty('ui')) { node.ui = null; delete node.ui; } }, createLinkUi = function (link) { - var linkUI = graphics.link(link); - link.ui = linkUI; - graphics.initLink(linkUI); + var linkUI = graphics.addLink(link); + if (settings.compatible) { + link.ui = linkUI; + } if (!graphics.omitLinksRendering) { renderLink(link); @@ -211,8 +218,8 @@ Viva.Graph.View.renderer = function (graph, settings) { }, removeLinkUi = function (link) { - if (link.hasOwnProperty('ui')) { - graphics.releaseLink(link.ui); + graphics.releaseLink(link); + if (settings.compatible && link.hasOwnProperty('ui')) { link.ui = null; delete link.ui; } @@ -224,20 +231,23 @@ Viva.Graph.View.renderer = function (graph, settings) { // TODO: This may not be memory efficient. Consider reusing handlers object. inputManager.bindDragNDrop(node, { onStart : function () { - wasPinned = node.isPinned; - node.isPinned = true; + wasPinned = layout.isNodePinned(node); + layout.pinNode(node, true); userInteraction = true; resetStable(); }, onDrag : function (e, offset) { - node.position.x += offset.x / transform.scale; - node.position.y += offset.y / transform.scale; + var oldPos = layout.getNodePosition(node.id); + layout.setNodePosition(node, + oldPos.x + offset.x / transform.scale, + oldPos.y + offset.y / transform.scale); + userInteraction = true; renderGraph(); }, onStop : function () { - node.isPinned = wasPinned; + layout.pinNode(node, wasPinned); userInteraction = false; } }); diff --git a/src/View/svgGraphics.js b/src/View/svgGraphics.js index a0f24d8..b325d80 100644 --- a/src/View/svgGraphics.js +++ b/src/View/svgGraphics.js @@ -16,6 +16,8 @@ Viva.Graph.View.svgGraphics = function () { offsetX, offsetY, actualScale = 1, + allNodes = {}, + allLinks = {}, /*jshint unused: false */ nodeBuilder = function (node) { return Viva.Graph.svg("rect") @@ -55,51 +57,53 @@ Viva.Graph.View.svgGraphics = function () { }; var graphics = { + getNodeUI: function (nodeId) { + return allNodes[nodeId]; + }, + + getLinkUI: function (linkId) { + return allLinks[linkId]; + }, /** - * Sets the collback that creates node representation or creates a new node - * presentation if builderCallbackOrNode is not a function. + * Sets the collback that creates node representation. * - * @param builderCallbackOrNode a callback function that accepts graph node - * as a parameter and must return an element representing this node. OR - * if it's not a function it's treated as a node to which DOM element should be created. + * @param builderCallback a callback function that accepts graph node + * as a parameter and must return an element representing this node. * * @returns If builderCallbackOrNode is a valid callback function, instance of this is returned; - * Otherwise a node representation is returned for the passed parameter. + * Otherwise undefined value is returned */ - node : function (builderCallbackOrNode) { - - if (builderCallbackOrNode && typeof builderCallbackOrNode !== "function") { - return nodeBuilder(builderCallbackOrNode); + node : function (builderCallback) { + if (typeof builderCallback !== "function") { + return; // todo: throw? this is not compatible with old versions } - nodeBuilder = builderCallbackOrNode; + nodeBuilder = builderCallback; return this; }, /** - * Sets the collback that creates link representation or creates a new link - * presentation if builderCallbackOrLink is not a function. + * Sets the callback that creates link representation * - * @param builderCallbackOrLink a callback function that accepts graph link - * as a parameter and must return an element representing this link. OR - * if it's not a function it's treated as a link to which DOM element should be created. + * @param builderCallback a callback function that accepts graph link + * as a parameter and must return an element representing this link. * - * @returns If builderCallbackOrLink is a valid callback function, instance of this is returned; - * Otherwise a link representation is returned for the passed parameter. + * @returns If builderCallback is a valid callback function, instance of this is returned; + * Otherwise undefined value is returend. */ - link : function (builderCallbackOrLink) { - if (builderCallbackOrLink && typeof builderCallbackOrLink !== "function") { - return linkBuilder(builderCallbackOrLink); + link : function (builderCallback) { + if (typeof builderCallback !== "function") { + return; // todo: throw? this is not compatible with old versions } - linkBuilder = builderCallbackOrLink; + linkBuilder = builderCallback; return this; }, /** * Allows to override default position setter for the node with a new - * function. newPlaceCallback(nodeUI, position) is function which + * function. newPlaceCallback(nodeUI, position, node) is function which * is used by updateNodePosition(). */ placeNode : function (newPlaceCallback) { @@ -215,13 +219,16 @@ Viva.Graph.View.svgGraphics = function () { * * @param linkUI visual representation of the link created by link() execution. */ - initLink : function (linkUI) { + addLink: function (link) { + var linkUI = linkBuilder(link); if (!linkUI) { return; } + allLinks[link.id] = linkUI; if (svgContainer.childElementCount > 0) { svgContainer.insertBefore(linkUI, svgContainer.firstChild); } else { svgContainer.appendChild(linkUI); } + return linkUI; }, /** @@ -230,7 +237,8 @@ Viva.Graph.View.svgGraphics = function () { * * @param linkUI visual representation of the link created by link() execution. **/ - releaseLink : function (linkUI) { + releaseLink : function (link) { + var linkUI = this.getLinkUI(link); svgContainer.removeChild(linkUI); }, @@ -240,26 +248,40 @@ Viva.Graph.View.svgGraphics = function () { * * @param nodeUI visual representation of the node created by node() execution. **/ - initNode : function (nodeUI) { + addNode : function (node) { + var nodeUI = nodeBuilder(node); + if (!nodeUI) { + return; + } + allNodes[node.id] = nodeUI; + svgContainer.appendChild(nodeUI); + + return nodeUI; }, /** * Called by Viva.Graph.View.renderer to let concrete graphic output * provider remove node from rendering surface. * - * @param nodeUI visual representation of the node created by node() execution. + * @param node graph's node **/ - releaseNode : function (nodeUI) { - svgContainer.removeChild(nodeUI); + releaseNode : function (node) { + var nodeUI = this.getNodeUI(node.id); + if (nodeUI) { + svgContainer.removeChild(nodeUI); + } }, /** * Called by Viva.Graph.View.renderer to let concrete graphic output * provider place given node UI to recommended position pos {x, y}; */ - updateNodePosition : function (nodeUI, pos) { - nodePositionCallback(nodeUI, pos); + updateNodePosition : function (node, pos) { + var ui = this.getNodeUI(node.id); + if (ui) { + nodePositionCallback(ui, pos, node); + } }, /** @@ -267,7 +289,8 @@ Viva.Graph.View.svgGraphics = function () { * provider place given link of the graph. Pos objects are {x, y}; */ updateLinkPosition : function (link, fromPos, toPos) { - linkPositionCallback(link, fromPos, toPos); + var ui = this.getLinkUI(link.id); + linkPositionCallback(ui, fromPos, toPos, link); }, /** From 709fadf4b9f634012b2a70ff746fff80d83269f2 Mon Sep 17 00:00:00 2001 From: anvaka Date: Thu, 8 Aug 2013 00:56:14 -0700 Subject: [PATCH 012/276] Trying to avoid link id duplicates. Not perfect, but should work most of the time. --- src/Core/graph.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Core/graph.js b/src/Core/graph.js index ba49f5b..b0c5227 100644 --- a/src/Core/graph.js +++ b/src/Core/graph.js @@ -148,7 +148,7 @@ Viva.Graph.graph = function () { var fromNode = this.getNode(fromId) || this.addNode(fromId); var toNode = this.getNode(toId) || this.addNode(toId); - var linkId = fromId.toString() + toId.toString(); + var linkId = fromId.toString() +'👉 ' + toId.toString(); var isMultiEdge = multiEdges.hasOwnProperty(linkId); if (isMultiEdge || this.hasLink(fromId, toId)) { if (!isMultiEdge) { @@ -351,9 +351,9 @@ Viva.Graph.graph = function () { * data - additional data passed to graph.addLink() method. */ forEachLink : function (callback) { - var i; + var i, length; if (typeof callback === 'function') { - for (i = 0; i < links.length; ++i) { + for (i = 0, length = links.length; i < length; ++i) { callback(links[i]); } } From cdcd32da0770d8162452e91c3dda17d416635103 Mon Sep 17 00:00:00 2001 From: anvaka Date: Thu, 8 Aug 2013 00:59:49 -0700 Subject: [PATCH 013/276] Decoupled node model from webgl renderer. Made webgl renderer 9% faster. Alas this breaks backwards compatibility --- src/Input/webglInputManager.js | 10 +- src/Layout/forceDirected.js | 21 ++++ src/View/renderer.js | 74 ++--------- src/View/svgGraphics.js | 3 +- src/View/webglGraphics.js | 220 +++++++++++++++++++-------------- src/WebGL/webglInputEvents.js | 24 ++-- src/WebGL/webglNodeProgram.js | 2 +- 7 files changed, 176 insertions(+), 178 deletions(-) diff --git a/src/Input/webglInputManager.js b/src/Input/webglInputManager.js index 8d7b659..9895cf0 100644 --- a/src/Input/webglInputManager.js +++ b/src/Input/webglInputManager.js @@ -4,7 +4,7 @@ Viva.Input = Viva.Input || {}; Viva.Input.webglInputManager = function (graph, graphics) { - var inputEvents = Viva.Graph.webglInputEvents(graphics, graph), + var inputEvents = Viva.Graph.webglInputEvents(graphics), draggedNode = null, internalHandlers = {}, pos = {x : 0, y : 0}; @@ -16,7 +16,7 @@ Viva.Input.webglInputManager = function (graph, graphics) { inputEvents.mouseCapture(draggedNode); - var handlers = internalHandlers[node.ui.id]; + var handlers = internalHandlers[node.id]; if (handlers && handlers.onStart) { handlers.onStart(e, pos); } @@ -26,14 +26,14 @@ Viva.Input.webglInputManager = function (graph, graphics) { inputEvents.releaseMouseCapture(draggedNode); draggedNode = null; - var handlers = internalHandlers[node.ui.id]; + var handlers = internalHandlers[node.id]; if (handlers && handlers.onStop) { handlers.onStop(); } return true; }).mouseMove(function (node, e) { if (draggedNode) { - var handlers = internalHandlers[draggedNode.ui.id]; + var handlers = internalHandlers[draggedNode.id]; if (handlers && handlers.onDrag) { handlers.onDrag(e, {x : e.clientX - pos.x, y : e.clientY - pos.y }); } @@ -57,7 +57,7 @@ Viva.Input.webglInputManager = function (graph, graphics) { * onStop: function() */ bindDragNDrop : function (node, handlers) { - internalHandlers[node.ui.id] = handlers; + internalHandlers[node.id] = handlers; } }; }; diff --git a/src/Layout/forceDirected.js b/src/Layout/forceDirected.js index 4c1a408..267b5ca 100644 --- a/src/Layout/forceDirected.js +++ b/src/Layout/forceDirected.js @@ -321,6 +321,27 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { return body && body.location; }, + getBoundNodePosition: function (node) { + var body = getBody(node.id); + if (!body) { + initNode(node); + body = getBody(node.id); + } + return body.location; + }, + + getBoundLinkPosition: function (link) { + var fromNode = graph.getNode(link.fromId), + toNode = graph.getNode(link.toId), + boundFrom = this.getBoundNodePosition(fromNode), + boundTo = this.getBoundNodePosition(toNode); + + return { + from : boundFrom, + to : boundTo + }; + }, + setNodePosition: function (node, x, y) { var body = getBody(node.id); if (body) { diff --git a/src/View/renderer.js b/src/View/renderer.js index 1d2514a..184caea 100644 --- a/src/View/renderer.js +++ b/src/View/renderer.js @@ -37,13 +37,7 @@ Viva.Graph.View = Viva.Graph.View || {}; * // Number of layout iterations to run before displaying the graph. The bigger you set this number * // the closer to ideal position graph will apper first time. But be careful: for large graphs * // it can freeze the browser. - * prerender : 0, - * - * // Renderer should be compatible with older version of VivaGraph. - * // Warning: This option will be depricated soon. Compatible mode has a flaw of data being - * // shared on a node object of a graph. Which makes it impossible to reuse between multiple - * // renderers/layouters. - * compatible: false + * prerender : 0 * } */ Viva.Graph.View.renderer = function (graph, settings) { @@ -86,52 +80,22 @@ Viva.Graph.View.renderer = function (graph, settings) { settings.renderLinks = true; } - settings.compatible = settings.compatible || false; settings.prerender = settings.prerender || 0; inputManager = (graphics.inputManager || Viva.Input.domInputManager)(graph, graphics); }, - // Cache positions object to prevent GC pressure - cachedFromPos = {x : 0, y : 0, node: null}, - cachedToPos = {x : 0, y : 0, node: null}, - cachedNodePos = { x: 0, y: 0}, windowEvents = Viva.Graph.Utils.events(window), publicEvents = Viva.Graph.Utils.events({}).extend(), graphEvents, containerDrag, - - renderLink = function (link) { - var fromNode = layout.getNodePosition(link.fromId), - toNode = layout.getNodePosition(link.toId); - - if (!fromNode || !toNode) { - return; - } - - cachedFromPos.x = fromNode.x; - cachedFromPos.y = fromNode.y; - - cachedToPos.x = toNode.x; - cachedToPos.y = toNode.y; - - graphics.updateLinkPosition(link, cachedFromPos, cachedToPos); - }, - - renderNode = function (node) { - var pos = layout.getNodePosition(node.id); - cachedNodePos.x = pos.x; - cachedNodePos.y = pos.y; - - graphics.updateNodePosition(node, cachedNodePos); - }, - renderGraph = function () { graphics.beginRender(); - if (settings.renderLinks && !graphics.omitLinksRendering) { - graph.forEachLink(renderLink); - } - graph.forEachNode(renderNode); + // todo: move this check graphics + if (settings.renderLinks) { + graphics.renderLinks(); + } + graphics.renderNodes(); graphics.endRender(); }, @@ -190,39 +154,21 @@ Viva.Graph.View.renderer = function (graph, settings) { }, createNodeUi = function (node) { - var nodeUI = graphics.addNode(node); - if (settings.compatible) { - node.ui = nodeUI; - } - - renderNode(node); + var boundPosition = layout.getBoundNodePosition(node); + graphics.addNode(node, boundPosition); }, removeNodeUi = function (node) { graphics.releaseNode(node); - if (settings.compatible && node.hasOwnProperty('ui')) { - node.ui = null; - delete node.ui; - } }, createLinkUi = function (link) { - var linkUI = graphics.addLink(link); - if (settings.compatible) { - link.ui = linkUI; - } - - if (!graphics.omitLinksRendering) { - renderLink(link); - } + var boundLinkPosition = layout.getBoundLinkPosition(link); + graphics.addLink(link, boundLinkPosition); }, removeLinkUi = function (link) { graphics.releaseLink(link); - if (settings.compatible && link.hasOwnProperty('ui')) { - link.ui = null; - delete link.ui; - } }, listenNodeEvents = function (node) { diff --git a/src/View/svgGraphics.js b/src/View/svgGraphics.js index b325d80..3f911c6 100644 --- a/src/View/svgGraphics.js +++ b/src/View/svgGraphics.js @@ -64,6 +64,7 @@ Viva.Graph.View.svgGraphics = function () { getLinkUI: function (linkId) { return allLinks[linkId]; }, + /** * Sets the collback that creates node representation. * @@ -217,7 +218,7 @@ Viva.Graph.View.svgGraphics = function () { * Called by Viva.Graph.View.renderer to let concrete graphic output * provider prepare to render given link of the graph * - * @param linkUI visual representation of the link created by link() execution. + * @param link - model of a link */ addLink: function (link) { var linkUI = linkBuilder(link); diff --git a/src/View/webglGraphics.js b/src/View/webglGraphics.js index 4953832..a35d763 100644 --- a/src/View/webglGraphics.js +++ b/src/View/webglGraphics.js @@ -43,6 +43,8 @@ Viva.Graph.View.webglGraphics = function (options) { links = [], initCallback, + allNodes = {}, + allLinks = {}, linkProgram = Viva.Graph.View.webglLinkProgram(), nodeProgram = Viva.Graph.View.webglNodeProgram(), /*jshint unused: false */ @@ -76,75 +78,57 @@ Viva.Graph.View.webglGraphics = function (options) { } }, - nodeBuilderInternal = function (node) { - var nodeId = nodesCount++, - ui = nodeUIBuilder(node); - ui.id = nodeId; - - nodeProgram.createNode(ui); - - nodes[nodeId] = node; - return ui; - }, - - linkBuilderInternal = function (link) { - var linkId = linksCount++, - ui = linkUIBuilder(link); - ui.id = linkId; - - linkProgram.createLink(ui); - - links[linkId] = link; - return ui; - }, - fireRescaled = function (graphics) { graphics.fire("rescaled"); }; var graphics = { + getLinkUI: function (linkId) { + return allLinks[linkId]; + }, + + getNodeUI: function (nodeId) { + return allNodes[nodeId]; + }, + /** - * Sets the collback that creates node representation or creates a new node - * presentation if builderCallbackOrNode is not a function. + * Sets the collback that creates node representation. * - * @param builderCallbackOrNode a callback function that accepts graph node - * as a parameter and must return an element representing this node. OR - * if it's not a function it's treated as a node to which DOM element should be created. + * @param builderCallback a callback function that accepts graph node + * as a parameter and must return an element representing this node. * * @returns If builderCallbackOrNode is a valid callback function, instance of this is returned; - * Otherwise a node representation is returned for the passed parameter. + * Otherwise undefined value is returned */ - node : function (builderCallbackOrNode) { - if (builderCallbackOrNode && typeof builderCallbackOrNode !== "function") { - return nodeBuilderInternal(builderCallbackOrNode); // create ui for node using current nodeUIBuilder + node : function (builderCallback) { + if (typeof builderCallback !== "function") { + return; // todo: throw? this is not compatible with old versions } - nodeUIBuilder = builderCallbackOrNode; // else replace ui builder with provided function. + nodeUIBuilder = builderCallback; return this; }, /** - * Sets the collback that creates link representation or creates a new link - * presentation if builderCallbackOrLink is not a function. + * Sets the callback that creates link representation * - * @param builderCallbackOrLink a callback function that accepts graph link - * as a parameter and must return an element representing this link. OR - * if it's not a function it's treated as a link to which DOM element should be created. + * @param builderCallback a callback function that accepts graph link + * as a parameter and must return an element representing this link. * - * @returns If builderCallbackOrLink is a valid callback function, instance of this is returned; - * Otherwise a link representation is returned for the passed parameter. + * @returns If builderCallback is a valid callback function, instance of this is returned; + * Otherwise undefined value is returend. */ - link : function (builderCallbackOrLink) { - - if (builderCallbackOrLink && typeof builderCallbackOrLink !== "function") { - return linkBuilderInternal(builderCallbackOrLink); + link : function (builderCallback) { + if (typeof builderCallback !== "function") { + return; // todo: throw? this is not compatible with old versions } - linkUIBuilder = builderCallbackOrLink; + linkUIBuilder = builderCallback; return this; }, + /** * Allows to override default position setter for the node with a new * function. newPlaceCallback(nodeUI, position) is function which @@ -210,23 +194,45 @@ Viva.Graph.View.webglGraphics = function (options) { updateSize(); }, - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render given link of the graph - * - * @param linkUI visual representation of the link created by link() execution. - */ - initLink : function (linkUI) { + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render given link of the graph + * + * @param link - model of a link + */ + addLink: function (link, boundPosition) { + var uiid = linksCount++, + ui = linkUIBuilder(link); + ui.id = uiid; + ui.pos = boundPosition; + + linkProgram.createLink(ui); + + links[uiid] = ui; + allLinks[link.id] = ui; + return ui; }, + /** * Called by Viva.Graph.View.renderer to let concrete graphic output * provider prepare to render given node of the graph. * * @param nodeUI visual representation of the node created by node() execution. **/ - initNode : function (nodeUI) { + addNode : function (node, boundPosition) { + var uiid = nodesCount++, + ui = nodeUIBuilder(node); + + ui.id = uiid; + ui.position = boundPosition; + ui.node = node; + + nodeProgram.createNode(ui); + + nodes[uiid] = ui; + allNodes[node.id] = ui; + return ui; }, -/*jshint unused: true */ translateRel : function (dx, dy) { transform[12] += (2 * transform[0] * dx / width) / transform[0]; @@ -346,21 +352,22 @@ Viva.Graph.View.webglGraphics = function (options) { * * @param linkUI visual representation of the link created by link() execution. **/ - releaseLink : function (linkToRemove) { + releaseLink : function (link) { if (linksCount > 0) { linksCount -= 1; } + var linkUI = allLinks[link.id]; + delete allLinks[link.id]; - linkProgram.removeLink(linkToRemove); + linkProgram.removeLink(linkUI); - var linkIdToRemove = linkToRemove.id; + var linkIdToRemove = linkUI.id; if (linkIdToRemove < linksCount) { if (linksCount === 0 || linksCount === linkIdToRemove) { return; // no more links or removed link is the last one. } - // TODO: consider getting rid of this. The only reason why it's here is to update 'ui' property - // so that renderer will pass proper id in updateLinkPosition. - links[linkIdToRemove] = links[linksCount]; - links[linkIdToRemove].ui.id = linkIdToRemove; + var lastLinkUI = links[linksCount]; + links[linkIdToRemove] = lastLinkUI; + lastLinkUI.id = linkIdToRemove; } }, @@ -370,61 +377,67 @@ Viva.Graph.View.webglGraphics = function (options) { * * @param nodeUI visual representation of the node created by node() execution. **/ - releaseNode : function (nodeUI) { + releaseNode : function (node) { if (nodesCount > 0) { nodesCount -= 1; } + var nodeUI = allNodes[node.id]; + delete allNodes[node.id]; nodeProgram.removeNode(nodeUI); - if (nodeUI.id < nodesCount) { - var nodeIdToRemove = nodeUI.id; + var nodeIdToRemove = nodeUI.id; + if (nodeIdToRemove < nodesCount) { if (nodesCount === 0 || nodesCount === nodeIdToRemove) { return; // no more nodes or removed node is the last in the list. } - var lastNode = nodes[nodesCount], - replacedNode = nodes[nodeIdToRemove]; + var lastNodeUI = nodes[nodesCount]; - nodes[nodeIdToRemove] = lastNode; - nodes[nodeIdToRemove].ui.id = nodeIdToRemove; + nodes[nodeIdToRemove] = lastNodeUI; + lastNodeUI.id = nodeIdToRemove; // Since concrete shaders may cache properties in the ui element // we are letting them to make this swap (e.g. image node shader // uses this approach to update node's offset in the atlas) - nodeProgram.replaceProperties(replacedNode.ui, lastNode.ui); + nodeProgram.replaceProperties(nodeUI, lastNodeUI); } }, - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider place given node UI to recommended position pos {x, y}; - */ - updateNodePosition : function (nodeUI, pos) { + renderNodes: function () { + var pos = {x : 0, y : 0}; // WebGL coordinate system is different. Would be better // to have this transform in the shader code, but it would // require every shader to be updated.. - pos.y = -pos.y; - if (userPlaceNodeCallback) { - userPlaceNodeCallback(nodeUI, pos); - } + for (var i = 0; i < nodesCount; ++i) { + var ui = nodes[i]; + pos.x = ui.position.x; + pos.y = -ui.position.y; + if (userPlaceNodeCallback) { + userPlaceNodeCallback(ui, pos); + } - nodeProgram.position(nodeUI, pos); + nodeProgram.position(ui, pos); + } }, - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider place given link of the graph. Pos objects are {x, y}; - */ - updateLinkPosition : function (link, fromPos, toPos) { - // WebGL coordinate system is different. Would be better - // to have this transform in the shader code, but it would - // require every shader to be updated.. - fromPos.y = -fromPos.y; - toPos.y = -toPos.y; - if (userPlaceLinkCallback) { - userPlaceLinkCallback(link, fromPos, toPos); - } + renderLinks: function () { + if (this.omitLinksRendering) { return; } + + var toPos = {x : 0, y : 0}; + var fromPos = {x : 0, y : 0}; + for (var i = 0; i < linksCount; ++i) { + var ui = links[i]; + var pos = ui.pos.from; + fromPos.x = pos.x; + fromPos.y = -pos.y; + pos = ui.pos.to; + toPos.x = pos.x; + toPos.y = -pos.y; + if (userPlaceLinkCallback) { + userPlaceLinkCallback(ui, fromPos, toPos); + } - linkProgram.position(link, fromPos, toPos); + linkProgram.position(ui, fromPos, toPos); + } }, /** @@ -473,7 +486,7 @@ Viva.Graph.View.webglGraphics = function (options) { // TODO: unload old shader and reinit. } }, - getGraphCoordinates : function (graphicsRootPos) { + transformClientToGraphCoordinates : function (graphicsRootPos) { // TODO: could be a problem when container has margins? // to save memory we modify incoming parameter: // point in clipspace coordinates: @@ -487,6 +500,25 @@ Viva.Graph.View.webglGraphics = function (options) { graphicsRootPos.y *= -height / 2; return graphicsRootPos; + }, + + getNodeAtClientPos: function (clientPos, preciseCheck) { + if (typeof preciseCheck !== "function") { + // we don't know anything about your node structure here :( + // potentially this could be delegated to node program, but for + // right now, we are giving up if you don't pass boundary check + // callback. It answers to a question is nodeUI covers (x, y) + return; + } + // first transform to graph coordinates: + this.transformClientToGraphCoordinates(clientPos); + // now using precise check iterate over each node and find one within box: + // TODO: This is poor O(N) performance. + for (var i = 0; i < nodesCount; ++i) { + if (preciseCheck(nodes[i], clientPos.x, clientPos.y)) { + return nodes[i].node; + } + } } }; @@ -494,4 +526,4 @@ Viva.Graph.View.webglGraphics = function (options) { Viva.Graph.Utils.events(graphics).extend(); return graphics; -}; \ No newline at end of file +}; diff --git a/src/WebGL/webglInputEvents.js b/src/WebGL/webglInputEvents.js index 653c0f9..22d6eb0 100644 --- a/src/WebGL/webglInputEvents.js +++ b/src/WebGL/webglInputEvents.js @@ -2,18 +2,17 @@ * Monitors graph-related mouse input in webgl graphics and notifies subscribers. * * @param {Viva.Graph.View.webglGraphics} webglGraphics - * @param {Viva.Graph.graph} graph */ -Viva.Graph.webglInputEvents = function (webglGraphics, graph) { +Viva.Graph.webglInputEvents = function (webglGraphics) { if (webglGraphics.webglInputEvents) { // Don't listen twice, if we are already attached to this graphics: return webglGraphics.webglInputEvents; } - var preciseCheck = function (node, x, y) { - if (node.ui && node.ui.size) { - var pos = node.position, - half = node.ui.size; + var preciseCheck = function (nodeUI, x, y) { + if (nodeUI && nodeUI.size) { + var pos = nodeUI.position, + half = nodeUI.size; return pos.x - half < x && x < pos.x + half && pos.y - half < y && y < pos.y + half; @@ -21,9 +20,11 @@ Viva.Graph.webglInputEvents = function (webglGraphics, graph) { return true; }, + getNodeAtClientPos = function (pos) { + return webglGraphics.getNodeAtClientPos(pos, preciseCheck); + }, mouseCapturedNode = null, - spatialIndex = Viva.Graph.spatialIndex(graph, preciseCheck), mouseEnterCallback = [], mouseLeaveCallback = [], mouseDownCallback = [], @@ -92,8 +93,7 @@ Viva.Graph.webglInputEvents = function (webglGraphics, graph) { pos.x = e.clientX - boundRect.left; pos.y = e.clientY - boundRect.top; - webglGraphics.getGraphCoordinates(pos); - node = spatialIndex.getNodeAt(pos.x, pos.y); + node = getNodeAtClientPos(pos); if (node && lastFound !== node) { lastFound = node; @@ -113,9 +113,8 @@ Viva.Graph.webglInputEvents = function (webglGraphics, graph) { pos.x = e.clientX - boundRect.left; pos.y = e.clientY - boundRect.top; - webglGraphics.getGraphCoordinates(pos); - args = [spatialIndex.getNodeAt(pos.x, pos.y), e]; + args = [getNodeAtClientPos(pos), e]; if (args[0]) { cancelBubble = invoke(mouseDownCallback, args); // we clicked on a node. Following drag should be handled on document events: @@ -140,9 +139,8 @@ Viva.Graph.webglInputEvents = function (webglGraphics, graph) { pos.x = e.clientX - boundRect.left; pos.y = e.clientY - boundRect.top; - webglGraphics.getGraphCoordinates(pos); - args = [spatialIndex.getNodeAt(pos.x, pos.y), e]; + args = [getNodeAtClientPos(pos), e]; if (args[0]) { window.document.onselectstart = prevSelectStart; diff --git a/src/WebGL/webglNodeProgram.js b/src/WebGL/webglNodeProgram.js index 8f413ff..f5f0110 100644 --- a/src/WebGL/webglNodeProgram.js +++ b/src/WebGL/webglNodeProgram.js @@ -139,4 +139,4 @@ Viva.Graph.View.webglNodeProgram = function () { gl.drawArrays(gl.POINTS, 0, nodesCount); } }; -}; \ No newline at end of file +}; From 19ab95d15f1ef07c47b79be1d0e220bcc5b3a2ec Mon Sep 17 00:00:00 2001 From: anvaka Date: Thu, 8 Aug 2013 01:43:06 -0700 Subject: [PATCH 014/276] Don't need this anymore --- src/Input/spatialIndex.js | 53 --------------------------------------- 1 file changed, 53 deletions(-) delete mode 100644 src/Input/spatialIndex.js diff --git a/src/Input/spatialIndex.js b/src/Input/spatialIndex.js deleted file mode 100644 index 3f21399..0000000 --- a/src/Input/spatialIndex.js +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Allows querying graph nodes position at given point. - * - * @param graph - graph to be queried. - * @param toleranceOrCheckCallback - if it's a number then it represents offest - * in pixels from any node position to be considered a part of the node. - * if it's a function then it's called for every node to check intersection - * - * TODO: currently it performes linear search. Use real spatial index to improve performance. - */ -Viva.Graph.spatialIndex = function (graph, toleranceOrCheckCallback) { - var getNodeFunction, - preciseCheckCallback, - tolerance = 16; - - if (typeof toleranceOrCheckCallback === 'function') { - preciseCheckCallback = toleranceOrCheckCallback; - getNodeFunction = function (x, y) { - var foundNode = null; - graph.forEachNode(function (node) { - if (preciseCheckCallback(node, x, y)) { - foundNode = node; - return true; - } - }); - - return foundNode; - }; - } else if (typeof toleranceOrCheckCallback === 'number') { - tolerance = toleranceOrCheckCallback; - getNodeFunction = function (x, y) { - var foundNode = null; - - graph.forEachNode(function (node) { - var pos = node.position; - - if (pos.x - tolerance < x && x < pos.x + tolerance && - pos.y - tolerance < y && y < pos.y + tolerance) { - - foundNode = node; - return true; - } - }); - - return foundNode; - }; - } - - - return { - getNodeAt : getNodeFunction - }; -}; From 132f686119c89056136b74e002a4eb49e5178b06 Mon Sep 17 00:00:00 2001 From: anvaka Date: Thu, 8 Aug 2013 01:54:44 -0700 Subject: [PATCH 015/276] Updated SVG graphics to match the renderer --- src/View/svgGraphics.js | 45 +++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/src/View/svgGraphics.js b/src/View/svgGraphics.js index 3f911c6..aae9ca8 100644 --- a/src/View/svgGraphics.js +++ b/src/View/svgGraphics.js @@ -220,9 +220,11 @@ Viva.Graph.View.svgGraphics = function () { * * @param link - model of a link */ - addLink: function (link) { + addLink: function (link, pos) { var linkUI = linkBuilder(link); if (!linkUI) { return; } + linkUI.position = pos; + linkUI.link = link; allLinks[link.id] = linkUI; if (svgContainer.childElementCount > 0) { svgContainer.insertBefore(linkUI, svgContainer.firstChild); @@ -249,11 +251,13 @@ Viva.Graph.View.svgGraphics = function () { * * @param nodeUI visual representation of the node created by node() execution. **/ - addNode : function (node) { + addNode : function (node, pos) { var nodeUI = nodeBuilder(node); if (!nodeUI) { return; } + nodeUI.position = pos; + nodeUI.node = node; allNodes[node.id] = nodeUI; svgContainer.appendChild(nodeUI); @@ -274,24 +278,31 @@ Viva.Graph.View.svgGraphics = function () { } }, - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider place given node UI to recommended position pos {x, y}; - */ - updateNodePosition : function (node, pos) { - var ui = this.getNodeUI(node.id); - if (ui) { - nodePositionCallback(ui, pos, node); + renderNodes : function () { + var pos = {x : 0, y: 0}; + for (var key in allNodes) { + if (allNodes.hasOwnProperty(key)) { + var nodeUI = allNodes[key]; + pos.x = nodeUI.position.x; + pos.y = nodeUI.position.y; + nodePositionCallback(nodeUI, pos, nodeUI.node); + } } }, - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider place given link of the graph. Pos objects are {x, y}; - */ - updateLinkPosition : function (link, fromPos, toPos) { - var ui = this.getLinkUI(link.id); - linkPositionCallback(ui, fromPos, toPos, link); + renderLinks : function () { + var fromPos = {x : 0, y: 0}, + toPos = {x : 0, y: 0}; + for (var key in allLinks) { + if (allLinks.hasOwnProperty(key)) { + var linkUI = allLinks[key]; + fromPos.x = linkUI.position.from.x; + fromPos.y = linkUI.position.from.y; + toPos.x = linkUI.position.to.x; + toPos.y = linkUI.position.to.y; + linkPositionCallback(linkUI, fromPos, toPos, linkUI.link); + } + } }, /** From 1aca5f019dbe26ebb6dbe6cad5d8ef3b4e7dec8a Mon Sep 17 00:00:00 2001 From: anvaka Date: Thu, 8 Aug 2013 10:04:02 -0700 Subject: [PATCH 016/276] Updated initial node placement logic --- src/Layout/forceDirected.js | 62 +++++-------------------------------- 1 file changed, 7 insertions(+), 55 deletions(-) diff --git a/src/Layout/forceDirected.js b/src/Layout/forceDirected.js index 267b5ca..018f11d 100644 --- a/src/Layout/forceDirected.js +++ b/src/Layout/forceDirected.js @@ -13,12 +13,6 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { } settings = Viva.lazyExtend(settings, { - /** - * If true, the layout API will be compatible with - * old version of the library, where each node had it's own - * position property. This was a bad API decision... - */ - compatible: false, /** * Ideal length for links (springs in physical model). */ @@ -65,7 +59,8 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { graphRect = new Viva.Graph.Rect(), random = Viva.random('ted.com', 103, 114, 101, 97, 116), - getBestBodyPosition = function(node) { + nodeBodies = {}, + getBestNodePosition = function(node) { // TODO: Initial position could be picked better, e.g. take into // account all neighbouring nodes/links, not only one. // How about center of mass? @@ -75,10 +70,10 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { if (node.links && node.links.length > 0) { var firstLink = node.links[0], - otherNode = firstLink.fromId !== node.id ? graph.getNode(firstLink.fromId) : graph.getNode(firstLink.toId); - if (otherNode.position) { - baseX = otherNode.position.x; - baseY = otherNode.position.y; + otherNode = firstLink.fromId !== node.id ? nodeBodies[firstLink.fromId] : nodeBodies[firstLink.toId]; + if (otherNode && otherNode.location) { + baseX = otherNode.location.x; + baseY = otherNode.location.y; } } @@ -88,7 +83,6 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { }; }, - nodeBodies = {}, getBody = function (nodeId) { return nodeBodies[nodeId]; }, @@ -110,19 +104,10 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { if (!body) { body = new Viva.Graph.Physics.Body(); nodeBodies[node.id] = body; - var position = getBestBodyPosition(body); + var position = getBestNodePosition(node); body.loc(position); updateBodyMass(node); - if (settings.compatible) { - // This is depricated method. Please never ever use - // 'compatible' mode: it has a curse of shared data store - // i.e. there is no way two layouters could layout the same - // graph, since they both would compete for positions - node.position = position; - node.force_directed_body = body; - } - forceSimulator.addBody(body); } }, @@ -130,10 +115,6 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { releaseNode = function(node) { var body = getBody(node.id); if (body) { - if (settings.compatible) { - node.force_directed_body = null; - delete node.force_directed_body; - } releaseBody(node); forceSimulator.removeBody(body); @@ -153,11 +134,6 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { // TODO: this has a bug, with multiple springs between same nodes springs[link.id] = spring; - - if (settings.compatible) { - // bad... - link.force_directed_spring = spring; - } }, releaseLink = function(link) { @@ -171,10 +147,6 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { if (to) { updateBodyMass(to); } - if (settings.compatible) { - link.force_directed_spring = null; - delete link.force_directed_spring; - } delete springs[link.id]; forceSimulator.removeSpring(spring); @@ -209,7 +181,6 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { }, isNodePinned = function(node, body) { - // this potentiall should make it easy to refactor when compatible mode goes away if (!node && !body) { return true; } @@ -253,25 +224,6 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { } } - if (settings.compatible) { - graph.forEachNode(function(node) { - var body = node.force_directed_body; - if (!body) { - // This could be a sign someone removed the propery. - // Please don't use 'compatible' mode - return; - } - - // if (isNodePinned(node)) { - // body.loc(node.position); - // } - - node.position.x = body.location.x; - node.position.y = body.location.y; - - }); - } - graphRect.x1 = x1; graphRect.x2 = x2; graphRect.y1 = y1; From 9d0dbabbbad97df93a0a808a2f241b1706adfcaa Mon Sep 17 00:00:00 2001 From: anvaka Date: Fri, 9 Aug 2013 09:43:59 -0700 Subject: [PATCH 017/276] Proper cleaning of input handlers in webgl input manager --- src/Input/webglInputManager.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Input/webglInputManager.js b/src/Input/webglInputManager.js index 9895cf0..7be7771 100644 --- a/src/Input/webglInputManager.js +++ b/src/Input/webglInputManager.js @@ -58,6 +58,9 @@ Viva.Input.webglInputManager = function (graph, graphics) { */ bindDragNDrop : function (node, handlers) { internalHandlers[node.id] = handlers; + if (!handlers) { + delete internalHandlers[node.id]; + } } }; }; From bf06e267d0623feeb10597541780b357edc7953e Mon Sep 17 00:00:00 2001 From: anvaka Date: Fri, 9 Aug 2013 09:44:57 -0700 Subject: [PATCH 018/276] Simplified force simulator --- src/Layout/forceDirected.js | 6 ++-- src/Physics/Forces/dragForce.js | 1 - src/Physics/Forces/gravityForce.js | 1 - src/Physics/Forces/nbodyForce.js | 4 +-- src/Physics/Forces/springForce.js | 2 -- src/Physics/forceSimulator.js | 51 +++++++++++++++--------------- 6 files changed, 30 insertions(+), 35 deletions(-) diff --git a/src/Layout/forceDirected.js b/src/Layout/forceDirected.js index 018f11d..dc6c7b4 100644 --- a/src/Layout/forceDirected.js +++ b/src/Layout/forceDirected.js @@ -230,9 +230,9 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { graphRect.y2 = y2; }; - forceSimulator.addSpringForce(springForce); - forceSimulator.addBodyForce(nbodyForce); - forceSimulator.addBodyForce(dragForce); + forceSimulator.setSpringForce(springForce); + forceSimulator.setNbodyForce(nbodyForce); + forceSimulator.setDragForce(dragForce); initSimulator(); diff --git a/src/Physics/Forces/dragForce.js b/src/Physics/Forces/dragForce.js index 590eca8..9bf3b30 100644 --- a/src/Physics/Forces/dragForce.js +++ b/src/Physics/Forces/dragForce.js @@ -8,7 +8,6 @@ Viva.Graph.Physics.dragForce = function (options) { }; return { - init : function (forceSimulator) {}, update : function (body) { body.force.x -= currentOptions.coeff * body.velocity.x; body.force.y -= currentOptions.coeff * body.velocity.y; diff --git a/src/Physics/Forces/gravityForce.js b/src/Physics/Forces/gravityForce.js index 9754939..244166b 100644 --- a/src/Physics/Forces/gravityForce.js +++ b/src/Physics/Forces/gravityForce.js @@ -10,7 +10,6 @@ Viva.Graph.Physics.gravityForce = function (gravityConstant, options) { return { - init : function (forceSimulator) {}, update : function (body) { var coeff = currentOptions.gravity * body.mass; diff --git a/src/Physics/Forces/nbodyForce.js b/src/Physics/Forces/nbodyForce.js index 0c3904e..5cf0758 100644 --- a/src/Physics/Forces/nbodyForce.js +++ b/src/Physics/Forces/nbodyForce.js @@ -253,7 +253,7 @@ Viva.Graph.Physics.nbodyForce = function (options) { // force it exerts on body b, and add this amount to b's net force. if ((node.right - node.left) / r < theta) { // in the if statement above we consider node's width only - // because the region was sqaurified during tree creation. + // because the region was squarified during tree creation. // Thus there is no difference between using width or height. v = gravity * node.mass * sourceBody.mass / (r * r * r); sourceBody.force.x = sourceBody.force.x + v * dx; @@ -324,4 +324,4 @@ Viva.Graph.Physics.nbodyForce = function (options) { return {gravity : gravity, theta : theta}; } }; -}; \ No newline at end of file +}; diff --git a/src/Physics/Forces/springForce.js b/src/Physics/Forces/springForce.js index 070a608..a5f5ede 100644 --- a/src/Physics/Forces/springForce.js +++ b/src/Physics/Forces/springForce.js @@ -7,8 +7,6 @@ Viva.Graph.Physics.springForce = function (currentOptions) { var random = Viva.random('Random number 4.', 'Chosen by fair dice roll'); return { - init : function (forceSimulator) {}, - update : function (spring) { var body1 = spring.body1, body2 = spring.body2, diff --git a/src/Physics/forceSimulator.js b/src/Physics/forceSimulator.js index 3df15c5..0cea585 100644 --- a/src/Physics/forceSimulator.js +++ b/src/Physics/forceSimulator.js @@ -12,8 +12,9 @@ Viva.Graph.Physics.forceSimulator = function (forceIntegrator) { var integrator = forceIntegrator, bodies = [], // Bodies in this simulation. springs = [], // Springs in this simulation. - bodyForces = [], // Forces acting on bodies. - springForces = []; // Forces acting on springs. + springForce, + nBodyForce, + dragForce; return { @@ -31,18 +32,9 @@ Viva.Graph.Physics.forceSimulator = function (forceIntegrator) { * Accumulates all forces acting on the bodies and springs. */ accumulate : function () { - var i, j, body; + var i, body; - // Reinitialize all forces - i = bodyForces.length; - while (i--) { - bodyForces[i].init(this); - } - - i = springForces.length; - while (i--) { - springForces[i].init(this); - } + nBodyForce.init(this); // Accumulate forces acting on bodies. i = bodies.length; @@ -51,16 +43,14 @@ Viva.Graph.Physics.forceSimulator = function (forceIntegrator) { body.force.x = 0; body.force.y = 0; - for (j = 0; j < bodyForces.length; j++) { - bodyForces[j].update(body); - } + nBodyForce.update(body); + dragForce.update(body); } // Accumulate forces acting on springs. - for (i = 0; i < springs.length; ++i) { - for (j = 0; j < springForces.length; j++) { - springForces[j].update(springs[i]); - } + i = springs.length; + while(i--) { + springForce.update(springs[i]); } }, @@ -135,29 +125,38 @@ Viva.Graph.Physics.forceSimulator = function (forceIntegrator) { }, /** - * Adds a force acting on all bodies in this simulation + * Sets n-body force acting on all bodies in this simulation */ - addBodyForce: function (force) { + setNbodyForce: function (force) { if (!force) { throw { message : 'Cannot add mighty (unknown) force to the simulator' }; } - bodyForces.push(force); + nBodyForce = force; }, + setDragForce: function (force) { + if (!force) { + throw { + message : 'Cannot add mighty (unknown) force to the simulator' + }; + } + + dragForce = force; + }, /** * Adds a spring force acting on all springs in this simulation. */ - addSpringForce : function (force) { + setSpringForce : function (force) { if (!force) { throw { message : 'Cannot add unknown force to the simulator' }; } - springForces.push(force); + springForce = force; } }; -}; \ No newline at end of file +}; From 4e89766c582bb2f380dc9d0ff6302fe15fbdb736 Mon Sep 17 00:00:00 2001 From: anvaka Date: Tue, 20 Aug 2013 00:33:45 -0700 Subject: [PATCH 019/276] Respecting original pinned mode for a node --- src/Layout/forceDirected.js | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/Layout/forceDirected.js b/src/Layout/forceDirected.js index dc6c7b4..802af88 100644 --- a/src/Layout/forceDirected.js +++ b/src/Layout/forceDirected.js @@ -99,6 +99,15 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { body.mass = 1 + graph.getLinks(node.id).length / 3.0; }, + isNodePinned = function(node, body) { + if (!node && !body) { + return true; + } + + return (node && (node.isPinned || (node.data && node.data.isPinned))) || + (body && body.isPinned); + }, + initNode = function(node) { var body = getBody(node.id); if (!body) { @@ -108,6 +117,9 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { body.loc(position); updateBodyMass(node); + if (isNodePinned(node)) { + body.isPinned = true; + } forceSimulator.addBody(body); } }, @@ -180,14 +192,6 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { graph.addEventListener('changed', onGraphChanged); }, - isNodePinned = function(node, body) { - if (!node && !body) { - return true; - } - - return (node && (node.isPinned || (node.data && node.data.isPinned))) || - (body && body.isPinned); - }, updateNodePositions = function() { var x1 = Number.MAX_VALUE, From e4e0e732777058d69b311ed86ec2c3933dac30b6 Mon Sep 17 00:00:00 2001 From: anvaka Date: Tue, 20 Aug 2013 00:34:12 -0700 Subject: [PATCH 020/276] Fixed broken test --- unit_tests/test_forceBasedLayout.js | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/unit_tests/test_forceBasedLayout.js b/unit_tests/test_forceBasedLayout.js index bef4d8a..ae59dcc 100644 --- a/unit_tests/test_forceBasedLayout.js +++ b/unit_tests/test_forceBasedLayout.js @@ -1,30 +1,31 @@ var test_forceBasedLayout = function(test) { - var assertGraphHasPositions = function(graph) { + var assertGraphHasPositions = function(graph, layout) { graph.forEachNode(function(node) { - test.assert(node.hasOwnProperty('position'), 'All nodes expected to have some position'); - test.assert(typeof node.position.x === 'number', 'Node position does not have a valid x position'); - test.assert(typeof node.position.y === 'number', 'Node position does not have a valid y position'); + var position = layout.getNodePosition(node.id); + test.assert(position, 'All nodes expected to have some position'); + test.assert(typeof position.x === 'number', 'Node position does not have a valid x position'); + test.assert(typeof position.y === 'number', 'Node position does not have a valid y position'); }); }; return { forceAttributesInitialized : function () { var graph = Viva.Graph.generator().path(2); - Viva.Graph.Layout.forceDirected(graph); - assertGraphHasPositions(graph); + var layout = Viva.Graph.Layout.forceDirected(graph); + assertGraphHasPositions(graph, layout); }, graphIsMonitored : function () { var graph = Viva.Graph.graph(); - Viva.Graph.Layout.forceDirected(graph); + var layout = Viva.Graph.Layout.forceDirected(graph); graph.addNode(1); - assertGraphHasPositions(graph); + assertGraphHasPositions(graph, layout); graph.addNode(2); - assertGraphHasPositions(graph); + assertGraphHasPositions(graph, layout); graph.addLink(1, 2); - assertGraphHasPositions(graph); + assertGraphHasPositions(graph, layout); graph.removeNode(1); - assertGraphHasPositions(graph); + assertGraphHasPositions(graph, layout); } }; }; From c11f7ca89d6c8967e70f443c8ee7a235dd7cec38 Mon Sep 17 00:00:00 2001 From: anvaka Date: Tue, 20 Aug 2013 00:34:56 -0700 Subject: [PATCH 021/276] One more performance test --- unit_tests/perf/perf_test.js | 1 + unit_tests/perf/switch_graphs.js | 54 ++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 unit_tests/perf/switch_graphs.js diff --git a/unit_tests/perf/perf_test.js b/unit_tests/perf/perf_test.js index 44829af..b38f726 100644 --- a/unit_tests/perf/perf_test.js +++ b/unit_tests/perf/perf_test.js @@ -13,6 +13,7 @@ var layoutIterations = 100; console.log('This is a very basic performance test of force directed layout'); console.log('V8 version: ' + process.versions.v8); +console.log('VivaGraph version: ' + Viva.Graph.version); var generator = Viva.Graph.generator(); var graph = generator.grid(gridSize, gridSize); console.log('Grid ' + gridSize + 'x' + gridSize + ', Nodes: ' + graph.getNodesCount() + ', Edges: ' + graph.getLinksCount()); diff --git a/unit_tests/perf/switch_graphs.js b/unit_tests/perf/switch_graphs.js new file mode 100644 index 0000000..fb2c456 --- /dev/null +++ b/unit_tests/perf/switch_graphs.js @@ -0,0 +1,54 @@ +// Testing behavior of graph cleanup and restart of layout +var Viva = require('../../dist/vivagraph'); +var gridSize = 100; +var layoutIterations = 30; +var repetition = 10; + +console.log('This is a very basic performance test of force directed layout'); +console.log('V8 version: ' + process.versions.v8); +console.log('VivaGraph version: ' + Viva.Graph.version); + +var graph = Viva.Graph.graph(); +var layout = Viva.Graph.Layout.forceDirected(graph); + +var i; +for (var r = 1; r < repetition + 1; ++r) { + console.time('Layout time'); + makeGrid(gridSize, gridSize, graph); + console.log(r + '. Performing ' + layoutIterations + ' iterations of layout'); + for (i = 0; i < layoutIterations; ++i) { + layout.step(); + } + makeComplete(gridSize, graph); + for (i = 0; i < layoutIterations; ++i) { + layout.step(); + } + console.timeEnd('Layout time'); + console.log('Finished step ' + r + '.'); +} + +function makeGrid(n, m, g) { + g.clear(); + g.beginUpdate(); + for (var i = 0; i < n; ++i) { + for (var j = 0; j < m; ++j) { + var node = i + j * n; + if (i > 0) { g.addLink(node, i - 1 + j * n); } + if (j > 0) { g.addLink(node, i + (j - 1) * n); } + } + } + g.endUpdate(); +} + +function makeComplete(n, g) { + g.clear(); + g.beginUpdate(); + for (var i = 0; i < n; ++i) { + for (var j = i + 1; j < n; ++j) { + if (i !== j) { + g.addLink(i, j); + } + } + } + g.endUpdate(); +} From 9dba964888de2c8df54b7f2120f45d29333c8a33 Mon Sep 17 00:00:00 2001 From: anvaka Date: Tue, 20 Aug 2013 00:44:46 -0700 Subject: [PATCH 022/276] Properly clean up svg graphics when node/link removed --- src/View/svgGraphics.js | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/View/svgGraphics.js b/src/View/svgGraphics.js index aae9ca8..6dd65e9 100644 --- a/src/View/svgGraphics.js +++ b/src/View/svgGraphics.js @@ -49,6 +49,10 @@ Viva.Graph.View.svgGraphics = function () { graphics.fire("rescaled"); }, + cachedPos = {x : 0, y: 0}, + cachedFromPos = {x : 0, y: 0}, + cachedToPos = {x : 0, y: 0}, + updateTransform = function () { if (svgContainer) { var transform = "matrix(" + actualScale + ", 0, 0," + actualScale + "," + offsetX + "," + offsetY + ")"; @@ -241,8 +245,11 @@ Viva.Graph.View.svgGraphics = function () { * @param linkUI visual representation of the link created by link() execution. **/ releaseLink : function (link) { - var linkUI = this.getLinkUI(link); - svgContainer.removeChild(linkUI); + var linkUI = allLinks[link.id]; + if (linkUI) { + svgContainer.removeChild(linkUI); + delete allLinks[link.id]; + } }, /** @@ -272,35 +279,33 @@ Viva.Graph.View.svgGraphics = function () { * @param node graph's node **/ releaseNode : function (node) { - var nodeUI = this.getNodeUI(node.id); + var nodeUI = allNodes[node.id]; if (nodeUI) { svgContainer.removeChild(nodeUI); + delete allNodes[node.id]; } }, renderNodes : function () { - var pos = {x : 0, y: 0}; for (var key in allNodes) { if (allNodes.hasOwnProperty(key)) { var nodeUI = allNodes[key]; - pos.x = nodeUI.position.x; - pos.y = nodeUI.position.y; - nodePositionCallback(nodeUI, pos, nodeUI.node); + cachedPos.x = nodeUI.position.x; + cachedPos.y = nodeUI.position.y; + nodePositionCallback(nodeUI, cachedPos, nodeUI.node); } } }, renderLinks : function () { - var fromPos = {x : 0, y: 0}, - toPos = {x : 0, y: 0}; for (var key in allLinks) { if (allLinks.hasOwnProperty(key)) { var linkUI = allLinks[key]; - fromPos.x = linkUI.position.from.x; - fromPos.y = linkUI.position.from.y; - toPos.x = linkUI.position.to.x; - toPos.y = linkUI.position.to.y; - linkPositionCallback(linkUI, fromPos, toPos, linkUI.link); + cachedFromPos.x = linkUI.position.from.x; + cachedFromPos.y = linkUI.position.from.y; + cachedToPos.x = linkUI.position.to.x; + cachedToPos.y = linkUI.position.to.y; + linkPositionCallback(linkUI, cachedFromPos, cachedToPos, linkUI.link); } } }, From ce0056fcfa88451d4d6fb507c83714803ab60aa9 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 7 Sep 2013 19:21:21 -0700 Subject: [PATCH 023/276] Updated bringToFront() to match new design --- src/View/webglGraphics.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/View/webglGraphics.js b/src/View/webglGraphics.js index a35d763..d56b9bb 100644 --- a/src/View/webglGraphics.js +++ b/src/View/webglGraphics.js @@ -181,9 +181,9 @@ Viva.Graph.View.webglGraphics = function (options) { temp = links[frontLinkId]; links[frontLinkId] = links[srcLinkId]; - links[frontLinkId].ui.id = frontLinkId; + links[frontLinkId].id = frontLinkId; links[srcLinkId] = temp; - links[srcLinkId].ui.id = srcLinkId; + links[srcLinkId].id = srcLinkId; } }, /*jshint unused: false */ @@ -508,7 +508,7 @@ Viva.Graph.View.webglGraphics = function (options) { // potentially this could be delegated to node program, but for // right now, we are giving up if you don't pass boundary check // callback. It answers to a question is nodeUI covers (x, y) - return; + return null; } // first transform to graph coordinates: this.transformClientToGraphCoordinates(clientPos); @@ -519,6 +519,7 @@ Viva.Graph.View.webglGraphics = function (options) { return nodes[i].node; } } + return null; } }; From 8d989b127927e58460540e5a8f350a4ac13f9095 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 7 Sep 2013 19:38:33 -0700 Subject: [PATCH 024/276] Unified svggraphics and webglgraphics for getGtaphicsRoot() --- src/View/svgGraphics.js | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/View/svgGraphics.js b/src/View/svgGraphics.js index 6dd65e9..fd59f28 100644 --- a/src/View/svgGraphics.js +++ b/src/View/svgGraphics.js @@ -15,6 +15,7 @@ Viva.Graph.View.svgGraphics = function () { svgRoot, offsetX, offsetY, + initCallback, actualScale = 1, allNodes = {}, allLinks = {}, @@ -206,6 +207,10 @@ Viva.Graph.View.svgGraphics = function () { svgRoot.appendChild(svgContainer); container.appendChild(svgRoot); updateTransform(); + // Notify the world if someoen waited for update. TODO: should send an event + if (typeof initCallback === "function") { + initCallback(svgRoot); + } }, /** @@ -310,11 +315,24 @@ Viva.Graph.View.svgGraphics = function () { } }, + /** + * Returns root element which hosts graphics. + */ + getGraphicsRoot : function (callbackWhenReady) { + // todo: should fire an event, instead of having this context. + if (typeof callbackWhenReady === "function") { + if (svgRoot) { + callbackWhenReady(svgRoot); + } else { + initCallback = callbackWhenReady; + } + } + return svgRoot; + }, /** * Returns root svg element. * * Note: This is internal method specific to this renderer - * TODO: Rename this to getGraphicsRoot() to be uniform accross graphics classes */ getSvgRoot : function () { return svgRoot; From a04d2c12ba8f174e8aaaec000578424ed6de840c Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 7 Sep 2013 22:27:26 -0700 Subject: [PATCH 025/276] Fixed infinite loop for large graphs --- src/Physics/Forces/nbodyForce.js | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Physics/Forces/nbodyForce.js b/src/Physics/Forces/nbodyForce.js index 5cf0758..f26ab80 100644 --- a/src/Physics/Forces/nbodyForce.js +++ b/src/Physics/Forces/nbodyForce.js @@ -94,11 +94,10 @@ Viva.Graph.Physics.nbodyForce = function (options) { root = newNode(), isSamePosition = function (point1, point2) { - // TODO: inline it? var dx = Math.abs(point1.x - point2.x); var dy = Math.abs(point1.y - point2.y); - return (dx < 0.01 && dy < 0.01); + return (dx < 1e-8 && dy < 1e-8); }, // Inserts body to the tree @@ -165,22 +164,23 @@ Viva.Graph.Physics.nbodyForce = function (options) { if (isSamePosition(oldBody.location, body.location)) { // Prevent infinite subdivision by bumping one node - // slightly. I assume this operation should be quite - // rare, that's why usage of cos()/sin() shouldn't hit performance. - var newX, newY; + // anywhere in this quadrant + if (node.right - node.left < 1e-8) { + // This is very bad, we ran out of precision. + // if we do not return from the method we'll get into + // infinite loop here. So we sacrifice correctness of layout, and keep the app running + return; + } do { - var angle = random.nextDouble() * 2 * Math.PI; - var dx = (node.right - node.left) * 0.006 * Math.cos(angle); - var dy = (node.bottom - node.top) * 0.006 * Math.sin(angle); + var offset = random.nextDouble(); + var dx = (node.right - node.left) * offset; + var dy = (node.bottom - node.top) * offset; - newX = oldBody.location.x + dx; - newY = oldBody.location.y + dy; + oldBody.location.x = node.left + dx; + oldBody.location.y = node.top + dy; // Make sure we don't bump it out of the box. If we do, next iteration should fix it - } while (newX < node.left || newX > node.right || - newY < node.top || newY > node.bottom); + } while (isSamePosition(oldBody.location, body.location)); - oldBody.location.x = newX; - oldBody.location.y = newY; } // Next iteration should subdivide node further. insertStack.push(node, oldBody); From 370212fbf24cd307434ed69577d17467f6a52431 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 7 Sep 2013 22:27:38 -0700 Subject: [PATCH 026/276] Version bump --- dist/vivagraph.js | 675 +++++++++++++++++++----------------------- dist/vivagraph.min.js | 4 +- src/version.js | 2 +- 3 files changed, 310 insertions(+), 371 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index e0cc1ba..b12289a 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -7,7 +7,7 @@ Viva.Graph = Viva.Graph || {}; if (typeof module !== 'undefined' && module.exports) { module.exports = Viva; } -Viva.Graph.version = '0.4.1'; +Viva.Graph.version = '0.5.0'; /** * Extends target object with given fields/values in the options object. * Unlike jQuery's extend this method does not override target object @@ -760,59 +760,6 @@ Viva.Input.domInputManager = function (graph, graphics) { } }; }; -/** - * Allows querying graph nodes position at given point. - * - * @param graph - graph to be queried. - * @param toleranceOrCheckCallback - if it's a number then it represents offest - * in pixels from any node position to be considered a part of the node. - * if it's a function then it's called for every node to check intersection - * - * TODO: currently it performes linear search. Use real spatial index to improve performance. - */ -Viva.Graph.spatialIndex = function (graph, toleranceOrCheckCallback) { - var getNodeFunction, - preciseCheckCallback, - tolerance = 16; - - if (typeof toleranceOrCheckCallback === 'function') { - preciseCheckCallback = toleranceOrCheckCallback; - getNodeFunction = function (x, y) { - var foundNode = null; - graph.forEachNode(function (node) { - if (preciseCheckCallback(node, x, y)) { - foundNode = node; - return true; - } - }); - - return foundNode; - }; - } else if (typeof toleranceOrCheckCallback === 'number') { - tolerance = toleranceOrCheckCallback; - getNodeFunction = function (x, y) { - var foundNode = null; - - graph.forEachNode(function (node) { - var pos = node.position; - - if (pos.x - tolerance < x && x < pos.x + tolerance && - pos.y - tolerance < y && y < pos.y + tolerance) { - - foundNode = node; - return true; - } - }); - - return foundNode; - }; - } - - - return { - getNodeAt : getNodeFunction - }; -}; /** * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com */ @@ -1262,7 +1209,7 @@ Viva.Graph.graph = function () { var fromNode = this.getNode(fromId) || this.addNode(fromId); var toNode = this.getNode(toId) || this.addNode(toId); - var linkId = fromId.toString() + toId.toString(); + var linkId = fromId.toString() +'👉 ' + toId.toString(); var isMultiEdge = multiEdges.hasOwnProperty(linkId); if (isMultiEdge || this.hasLink(fromId, toId)) { if (!isMultiEdge) { @@ -1465,9 +1412,9 @@ Viva.Graph.graph = function () { * data - additional data passed to graph.addLink() method. */ forEachLink : function (callback) { - var i; + var i, length; if (typeof callback === 'function') { - for (i = 0; i < links.length; ++i) { + for (i = 0, length = links.length; i < length; ++i) { callback(links[i]); } } @@ -1773,11 +1720,10 @@ Viva.Graph.Physics.nbodyForce = function (options) { root = newNode(), isSamePosition = function (point1, point2) { - // TODO: inline it? var dx = Math.abs(point1.x - point2.x); var dy = Math.abs(point1.y - point2.y); - return (dx < 0.01 && dy < 0.01); + return (dx < 1e-8 && dy < 1e-8); }, // Inserts body to the tree @@ -1844,22 +1790,23 @@ Viva.Graph.Physics.nbodyForce = function (options) { if (isSamePosition(oldBody.location, body.location)) { // Prevent infinite subdivision by bumping one node - // slightly. I assume this operation should be quite - // rare, that's why usage of cos()/sin() shouldn't hit performance. - var newX, newY; + // anywhere in this quadrant + if (node.right - node.left < 1e-8) { + // This is very bad, we ran out of precision. + // if we do not return from the method we'll get into + // infinite loop here. So we sacrifice correctness of layout, and keep the app running + return; + } do { - var angle = random.nextDouble() * 2 * Math.PI; - var dx = (node.right - node.left) * 0.006 * Math.cos(angle); - var dy = (node.bottom - node.top) * 0.006 * Math.sin(angle); + var offset = random.nextDouble(); + var dx = (node.right - node.left) * offset; + var dy = (node.bottom - node.top) * offset; - newX = oldBody.location.x + dx; - newY = oldBody.location.y + dy; + oldBody.location.x = node.left + dx; + oldBody.location.y = node.top + dy; // Make sure we don't bump it out of the box. If we do, next iteration should fix it - } while (newX < node.left || newX > node.right || - newY < node.top || newY > node.bottom); + } while (isSamePosition(oldBody.location, body.location)); - oldBody.location.x = newX; - oldBody.location.y = newY; } // Next iteration should subdivide node further. insertStack.push(node, oldBody); @@ -1932,7 +1879,7 @@ Viva.Graph.Physics.nbodyForce = function (options) { // force it exerts on body b, and add this amount to b's net force. if ((node.right - node.left) / r < theta) { // in the if statement above we consider node's width only - // because the region was sqaurified during tree creation. + // because the region was squarified during tree creation. // Thus there is no difference between using width or height. v = gravity * node.mass * sourceBody.mass / (r * r * r); sourceBody.force.x = sourceBody.force.x + v * dx; @@ -2003,7 +1950,8 @@ Viva.Graph.Physics.nbodyForce = function (options) { return {gravity : gravity, theta : theta}; } }; -};Viva.Graph.Physics.dragForce = function (options) { +}; +Viva.Graph.Physics.dragForce = function (options) { if (!options) { options = {}; } @@ -2013,7 +1961,6 @@ Viva.Graph.Physics.nbodyForce = function (options) { }; return { - init : function (forceSimulator) {}, update : function (body) { body.force.x -= currentOptions.coeff * body.velocity.x; body.force.y -= currentOptions.coeff * body.velocity.y; @@ -2038,8 +1985,6 @@ Viva.Graph.Physics.springForce = function (currentOptions) { var random = Viva.random('Random number 4.', 'Chosen by fair dice roll'); return { - init : function (forceSimulator) {}, - update : function (spring) { var body1 = spring.body1, body2 = spring.body2, @@ -2089,8 +2034,9 @@ Viva.Graph.Physics.forceSimulator = function (forceIntegrator) { var integrator = forceIntegrator, bodies = [], // Bodies in this simulation. springs = [], // Springs in this simulation. - bodyForces = [], // Forces acting on bodies. - springForces = []; // Forces acting on springs. + springForce, + nBodyForce, + dragForce; return { @@ -2108,18 +2054,9 @@ Viva.Graph.Physics.forceSimulator = function (forceIntegrator) { * Accumulates all forces acting on the bodies and springs. */ accumulate : function () { - var i, j, body; - - // Reinitialize all forces - i = bodyForces.length; - while (i--) { - bodyForces[i].init(this); - } + var i, body; - i = springForces.length; - while (i--) { - springForces[i].init(this); - } + nBodyForce.init(this); // Accumulate forces acting on bodies. i = bodies.length; @@ -2128,16 +2065,14 @@ Viva.Graph.Physics.forceSimulator = function (forceIntegrator) { body.force.x = 0; body.force.y = 0; - for (j = 0; j < bodyForces.length; j++) { - bodyForces[j].update(body); - } + nBodyForce.update(body); + dragForce.update(body); } // Accumulate forces acting on springs. - for (i = 0; i < springs.length; ++i) { - for (j = 0; j < springForces.length; j++) { - springForces[j].update(springs[i]); - } + i = springs.length; + while(i--) { + springForce.update(springs[i]); } }, @@ -2212,32 +2147,42 @@ Viva.Graph.Physics.forceSimulator = function (forceIntegrator) { }, /** - * Adds a force acting on all bodies in this simulation + * Sets n-body force acting on all bodies in this simulation */ - addBodyForce: function (force) { + setNbodyForce: function (force) { if (!force) { throw { message : 'Cannot add mighty (unknown) force to the simulator' }; } - bodyForces.push(force); + nBodyForce = force; }, + setDragForce: function (force) { + if (!force) { + throw { + message : 'Cannot add mighty (unknown) force to the simulator' + }; + } + + dragForce = force; + }, /** * Adds a spring force acting on all springs in this simulation. */ - addSpringForce : function (force) { + setSpringForce : function (force) { if (!force) { throw { message : 'Cannot add unknown force to the simulator' }; } - springForces.push(force); + springForce = force; } }; -};// I don't like to suppress this, but I'm afraid 'force_directed_body' +}; +// I don't like to suppress this, but I'm afraid 'force_directed_body' // could already be used by someone. Don't want to break it now. /* jshint camelcase:false */ @@ -2252,12 +2197,6 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { } settings = Viva.lazyExtend(settings, { - /** - * If true, the layout API will be compatible with - * old version of the library, where each node had it's own - * position property. This was a bad API decision... - */ - compatible: false, /** * Ideal length for links (springs in physical model). */ @@ -2304,7 +2243,8 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { graphRect = new Viva.Graph.Rect(), random = Viva.random('ted.com', 103, 114, 101, 97, 116), - getBestBodyPosition = function(node) { + nodeBodies = {}, + getBestNodePosition = function(node) { // TODO: Initial position could be picked better, e.g. take into // account all neighbouring nodes/links, not only one. // How about center of mass? @@ -2314,10 +2254,10 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { if (node.links && node.links.length > 0) { var firstLink = node.links[0], - otherNode = firstLink.fromId !== node.id ? graph.getNode(firstLink.fromId) : graph.getNode(firstLink.toId); - if (otherNode.position) { - baseX = otherNode.position.x; - baseY = otherNode.position.y; + otherNode = firstLink.fromId !== node.id ? nodeBodies[firstLink.fromId] : nodeBodies[firstLink.toId]; + if (otherNode && otherNode.location) { + baseX = otherNode.location.x; + baseY = otherNode.location.y; } } @@ -2327,7 +2267,6 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { }; }, - nodeBodies = {}, getBody = function (nodeId) { return nodeBodies[nodeId]; }, @@ -2344,24 +2283,27 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { body.mass = 1 + graph.getLinks(node.id).length / 3.0; }, + isNodePinned = function(node, body) { + if (!node && !body) { + return true; + } + + return (node && (node.isPinned || (node.data && node.data.isPinned))) || + (body && body.isPinned); + }, + initNode = function(node) { var body = getBody(node.id); if (!body) { body = new Viva.Graph.Physics.Body(); nodeBodies[node.id] = body; - var position = getBestBodyPosition(body); + var position = getBestNodePosition(node); body.loc(position); updateBodyMass(node); - if (settings.compatible) { - // This is depricated method. Please never ever use - // 'compatible' mode: it has a curse of shared data store - // i.e. there is no way two layouters could layout the same - // graph, since they both would compete for positions - node.position = position; - node.force_directed_body = body; + if (isNodePinned(node)) { + body.isPinned = true; } - forceSimulator.addBody(body); } }, @@ -2369,10 +2311,6 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { releaseNode = function(node) { var body = getBody(node.id); if (body) { - if (settings.compatible) { - node.force_directed_body = null; - delete node.force_directed_body; - } releaseBody(node); forceSimulator.removeBody(body); @@ -2392,11 +2330,6 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { // TODO: this has a bug, with multiple springs between same nodes springs[link.id] = spring; - - if (settings.compatible) { - // bad... - link.force_directed_spring = spring; - } }, releaseLink = function(link) { @@ -2410,10 +2343,6 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { if (to) { updateBodyMass(to); } - if (settings.compatible) { - link.force_directed_spring = null; - delete link.force_directed_spring; - } delete springs[link.id]; forceSimulator.removeSpring(spring); @@ -2447,15 +2376,6 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { graph.addEventListener('changed', onGraphChanged); }, - isNodePinned = function(node, body) { - // this potentiall should make it easy to refactor when compatible mode goes away - if (!node && !body) { - return true; - } - - return (node && (node.isPinned || (node.data && node.data.isPinned))) || - (body && body.isPinned); - }, updateNodePositions = function() { var x1 = Number.MAX_VALUE, @@ -2492,34 +2412,15 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { } } - if (settings.compatible) { - graph.forEachNode(function(node) { - var body = node.force_directed_body; - if (!body) { - // This could be a sign someone removed the propery. - // Please don't use 'compatible' mode - return; - } - - // if (isNodePinned(node)) { - // body.loc(node.position); - // } - - node.position.x = body.location.x; - node.position.y = body.location.y; - - }); - } - graphRect.x1 = x1; graphRect.x2 = x2; graphRect.y1 = y1; graphRect.y2 = y2; }; - forceSimulator.addSpringForce(springForce); - forceSimulator.addBodyForce(nbodyForce); - forceSimulator.addBodyForce(dragForce); + forceSimulator.setSpringForce(springForce); + forceSimulator.setNbodyForce(nbodyForce); + forceSimulator.setDragForce(dragForce); initSimulator(); @@ -2560,6 +2461,27 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { return body && body.location; }, + getBoundNodePosition: function (node) { + var body = getBody(node.id); + if (!body) { + initNode(node); + body = getBody(node.id); + } + return body.location; + }, + + getBoundLinkPosition: function (link) { + var fromNode = graph.getNode(link.fromId), + toNode = graph.getNode(link.toId), + boundFrom = this.getBoundNodePosition(fromNode), + boundTo = this.getBoundNodePosition(toNode); + + return { + from : boundFrom, + to : boundTo + }; + }, + setNodePosition: function (node, x, y) { var body = getBody(node.id); if (body) { @@ -2837,13 +2759,7 @@ Viva.Graph.View = Viva.Graph.View || {}; * // Number of layout iterations to run before displaying the graph. The bigger you set this number * // the closer to ideal position graph will apper first time. But be careful: for large graphs * // it can freeze the browser. - * prerender : 0, - * - * // Renderer should be compatible with older version of VivaGraph. - * // Warning: This option will be depricated soon. Compatible mode has a flaw of data being - * // shared on a node object of a graph. Which makes it impossible to reuse between multiple - * // renderers/layouters. - * compatible: false + * prerender : 0 * } */ Viva.Graph.View.renderer = function (graph, settings) { @@ -2886,52 +2802,22 @@ Viva.Graph.View.renderer = function (graph, settings) { settings.renderLinks = true; } - settings.compatible = settings.compatible || false; settings.prerender = settings.prerender || 0; inputManager = (graphics.inputManager || Viva.Input.domInputManager)(graph, graphics); }, - // Cache positions object to prevent GC pressure - cachedFromPos = {x : 0, y : 0, node: null}, - cachedToPos = {x : 0, y : 0, node: null}, - cachedNodePos = { x: 0, y: 0}, windowEvents = Viva.Graph.Utils.events(window), publicEvents = Viva.Graph.Utils.events({}).extend(), graphEvents, containerDrag, - - renderLink = function (link) { - var fromNode = layout.getNodePosition(link.fromId), - toNode = layout.getNodePosition(link.toId); - - if (!fromNode || !toNode) { - return; - } - - cachedFromPos.x = fromNode.x; - cachedFromPos.y = fromNode.y; - - cachedToPos.x = toNode.x; - cachedToPos.y = toNode.y; - - graphics.updateLinkPosition(link, cachedFromPos, cachedToPos); - }, - - renderNode = function (node) { - var pos = layout.getNodePosition(node.id); - cachedNodePos.x = pos.x; - cachedNodePos.y = pos.y; - - graphics.updateNodePosition(node, cachedNodePos); - }, - renderGraph = function () { graphics.beginRender(); - if (settings.renderLinks && !graphics.omitLinksRendering) { - graph.forEachLink(renderLink); - } - graph.forEachNode(renderNode); + // todo: move this check graphics + if (settings.renderLinks) { + graphics.renderLinks(); + } + graphics.renderNodes(); graphics.endRender(); }, @@ -2990,39 +2876,21 @@ Viva.Graph.View.renderer = function (graph, settings) { }, createNodeUi = function (node) { - var nodeUI = graphics.addNode(node); - if (settings.compatible) { - node.ui = nodeUI; - } - - renderNode(node); + var boundPosition = layout.getBoundNodePosition(node); + graphics.addNode(node, boundPosition); }, removeNodeUi = function (node) { graphics.releaseNode(node); - if (settings.compatible && node.hasOwnProperty('ui')) { - node.ui = null; - delete node.ui; - } }, createLinkUi = function (link) { - var linkUI = graphics.addLink(link); - if (settings.compatible) { - link.ui = linkUI; - } - - if (!graphics.omitLinksRendering) { - renderLink(link); - } + var boundLinkPosition = layout.getBoundLinkPosition(link); + graphics.addLink(link, boundLinkPosition); }, removeLinkUi = function (link) { graphics.releaseLink(link); - if (settings.compatible && link.hasOwnProperty('ui')) { - link.ui = null; - delete link.ui; - } }, listenNodeEvents = function (node) { @@ -4521,6 +4389,7 @@ Viva.Graph.View.svgGraphics = function () { svgRoot, offsetX, offsetY, + initCallback, actualScale = 1, allNodes = {}, allLinks = {}, @@ -4555,6 +4424,10 @@ Viva.Graph.View.svgGraphics = function () { graphics.fire("rescaled"); }, + cachedPos = {x : 0, y: 0}, + cachedFromPos = {x : 0, y: 0}, + cachedToPos = {x : 0, y: 0}, + updateTransform = function () { if (svgContainer) { var transform = "matrix(" + actualScale + ", 0, 0," + actualScale + "," + offsetX + "," + offsetY + ")"; @@ -4570,6 +4443,7 @@ Viva.Graph.View.svgGraphics = function () { getLinkUI: function (linkId) { return allLinks[linkId]; }, + /** * Sets the collback that creates node representation. * @@ -4707,6 +4581,10 @@ Viva.Graph.View.svgGraphics = function () { svgRoot.appendChild(svgContainer); container.appendChild(svgRoot); updateTransform(); + // Notify the world if someoen waited for update. TODO: should send an event + if (typeof initCallback === "function") { + initCallback(svgRoot); + } }, /** @@ -4723,11 +4601,13 @@ Viva.Graph.View.svgGraphics = function () { * Called by Viva.Graph.View.renderer to let concrete graphic output * provider prepare to render given link of the graph * - * @param linkUI visual representation of the link created by link() execution. + * @param link - model of a link */ - addLink: function (link) { + addLink: function (link, pos) { var linkUI = linkBuilder(link); if (!linkUI) { return; } + linkUI.position = pos; + linkUI.link = link; allLinks[link.id] = linkUI; if (svgContainer.childElementCount > 0) { svgContainer.insertBefore(linkUI, svgContainer.firstChild); @@ -4744,8 +4624,11 @@ Viva.Graph.View.svgGraphics = function () { * @param linkUI visual representation of the link created by link() execution. **/ releaseLink : function (link) { - var linkUI = this.getLinkUI(link); - svgContainer.removeChild(linkUI); + var linkUI = allLinks[link.id]; + if (linkUI) { + svgContainer.removeChild(linkUI); + delete allLinks[link.id]; + } }, /** @@ -4754,11 +4637,13 @@ Viva.Graph.View.svgGraphics = function () { * * @param nodeUI visual representation of the node created by node() execution. **/ - addNode : function (node) { + addNode : function (node, pos) { var nodeUI = nodeBuilder(node); if (!nodeUI) { return; } + nodeUI.position = pos; + nodeUI.node = node; allNodes[node.id] = nodeUI; svgContainer.appendChild(nodeUI); @@ -4773,37 +4658,55 @@ Viva.Graph.View.svgGraphics = function () { * @param node graph's node **/ releaseNode : function (node) { - var nodeUI = this.getNodeUI(node.id); + var nodeUI = allNodes[node.id]; if (nodeUI) { svgContainer.removeChild(nodeUI); + delete allNodes[node.id]; } }, - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider place given node UI to recommended position pos {x, y}; - */ - updateNodePosition : function (node, pos) { - var ui = this.getNodeUI(node.id); - if (ui) { - nodePositionCallback(ui, pos, node); + renderNodes : function () { + for (var key in allNodes) { + if (allNodes.hasOwnProperty(key)) { + var nodeUI = allNodes[key]; + cachedPos.x = nodeUI.position.x; + cachedPos.y = nodeUI.position.y; + nodePositionCallback(nodeUI, cachedPos, nodeUI.node); + } } }, - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider place given link of the graph. Pos objects are {x, y}; - */ - updateLinkPosition : function (link, fromPos, toPos) { - var ui = this.getLinkUI(link.id); - linkPositionCallback(ui, fromPos, toPos, link); + renderLinks : function () { + for (var key in allLinks) { + if (allLinks.hasOwnProperty(key)) { + var linkUI = allLinks[key]; + cachedFromPos.x = linkUI.position.from.x; + cachedFromPos.y = linkUI.position.from.y; + cachedToPos.x = linkUI.position.to.x; + cachedToPos.y = linkUI.position.to.y; + linkPositionCallback(linkUI, cachedFromPos, cachedToPos, linkUI.link); + } + } }, + /** + * Returns root element which hosts graphics. + */ + getGraphicsRoot : function (callbackWhenReady) { + // todo: should fire an event, instead of having this context. + if (typeof callbackWhenReady === "function") { + if (svgRoot) { + callbackWhenReady(svgRoot); + } else { + initCallback = callbackWhenReady; + } + } + return svgRoot; + }, /** * Returns root svg element. * * Note: This is internal method specific to this renderer - * TODO: Rename this to getGraphicsRoot() to be uniform accross graphics classes */ getSvgRoot : function () { return svgRoot; @@ -5279,7 +5182,8 @@ Viva.Graph.View.webglNodeProgram = function () { gl.drawArrays(gl.POINTS, 0, nodesCount); } }; -};/** +}; +/** * @fileOverview Defines a naive form of links for webglGraphics class. * This form allows to change color of links. * @@ -5896,6 +5800,8 @@ Viva.Graph.View.webglGraphics = function (options) { links = [], initCallback, + allNodes = {}, + allLinks = {}, linkProgram = Viva.Graph.View.webglLinkProgram(), nodeProgram = Viva.Graph.View.webglNodeProgram(), /*jshint unused: false */ @@ -5929,75 +5835,57 @@ Viva.Graph.View.webglGraphics = function (options) { } }, - nodeBuilderInternal = function (node) { - var nodeId = nodesCount++, - ui = nodeUIBuilder(node); - ui.id = nodeId; - - nodeProgram.createNode(ui); - - nodes[nodeId] = node; - return ui; - }, - - linkBuilderInternal = function (link) { - var linkId = linksCount++, - ui = linkUIBuilder(link); - ui.id = linkId; - - linkProgram.createLink(ui); - - links[linkId] = link; - return ui; - }, - fireRescaled = function (graphics) { graphics.fire("rescaled"); }; var graphics = { + getLinkUI: function (linkId) { + return allLinks[linkId]; + }, + + getNodeUI: function (nodeId) { + return allNodes[nodeId]; + }, + /** - * Sets the collback that creates node representation or creates a new node - * presentation if builderCallbackOrNode is not a function. + * Sets the collback that creates node representation. * - * @param builderCallbackOrNode a callback function that accepts graph node - * as a parameter and must return an element representing this node. OR - * if it's not a function it's treated as a node to which DOM element should be created. + * @param builderCallback a callback function that accepts graph node + * as a parameter and must return an element representing this node. * * @returns If builderCallbackOrNode is a valid callback function, instance of this is returned; - * Otherwise a node representation is returned for the passed parameter. + * Otherwise undefined value is returned */ - node : function (builderCallbackOrNode) { - if (builderCallbackOrNode && typeof builderCallbackOrNode !== "function") { - return nodeBuilderInternal(builderCallbackOrNode); // create ui for node using current nodeUIBuilder + node : function (builderCallback) { + if (typeof builderCallback !== "function") { + return; // todo: throw? this is not compatible with old versions } - nodeUIBuilder = builderCallbackOrNode; // else replace ui builder with provided function. + nodeUIBuilder = builderCallback; return this; }, /** - * Sets the collback that creates link representation or creates a new link - * presentation if builderCallbackOrLink is not a function. + * Sets the callback that creates link representation * - * @param builderCallbackOrLink a callback function that accepts graph link - * as a parameter and must return an element representing this link. OR - * if it's not a function it's treated as a link to which DOM element should be created. + * @param builderCallback a callback function that accepts graph link + * as a parameter and must return an element representing this link. * - * @returns If builderCallbackOrLink is a valid callback function, instance of this is returned; - * Otherwise a link representation is returned for the passed parameter. + * @returns If builderCallback is a valid callback function, instance of this is returned; + * Otherwise undefined value is returend. */ - link : function (builderCallbackOrLink) { - - if (builderCallbackOrLink && typeof builderCallbackOrLink !== "function") { - return linkBuilderInternal(builderCallbackOrLink); + link : function (builderCallback) { + if (typeof builderCallback !== "function") { + return; // todo: throw? this is not compatible with old versions } - linkUIBuilder = builderCallbackOrLink; + linkUIBuilder = builderCallback; return this; }, + /** * Allows to override default position setter for the node with a new * function. newPlaceCallback(nodeUI, position) is function which @@ -6050,9 +5938,9 @@ Viva.Graph.View.webglGraphics = function (options) { temp = links[frontLinkId]; links[frontLinkId] = links[srcLinkId]; - links[frontLinkId].ui.id = frontLinkId; + links[frontLinkId].id = frontLinkId; links[srcLinkId] = temp; - links[srcLinkId].ui.id = srcLinkId; + links[srcLinkId].id = srcLinkId; } }, /*jshint unused: false */ @@ -6063,23 +5951,45 @@ Viva.Graph.View.webglGraphics = function (options) { updateSize(); }, - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render given link of the graph - * - * @param linkUI visual representation of the link created by link() execution. - */ - initLink : function (linkUI) { + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render given link of the graph + * + * @param link - model of a link + */ + addLink: function (link, boundPosition) { + var uiid = linksCount++, + ui = linkUIBuilder(link); + ui.id = uiid; + ui.pos = boundPosition; + + linkProgram.createLink(ui); + + links[uiid] = ui; + allLinks[link.id] = ui; + return ui; }, + /** * Called by Viva.Graph.View.renderer to let concrete graphic output * provider prepare to render given node of the graph. * * @param nodeUI visual representation of the node created by node() execution. **/ - initNode : function (nodeUI) { + addNode : function (node, boundPosition) { + var uiid = nodesCount++, + ui = nodeUIBuilder(node); + + ui.id = uiid; + ui.position = boundPosition; + ui.node = node; + + nodeProgram.createNode(ui); + + nodes[uiid] = ui; + allNodes[node.id] = ui; + return ui; }, -/*jshint unused: true */ translateRel : function (dx, dy) { transform[12] += (2 * transform[0] * dx / width) / transform[0]; @@ -6199,21 +6109,22 @@ Viva.Graph.View.webglGraphics = function (options) { * * @param linkUI visual representation of the link created by link() execution. **/ - releaseLink : function (linkToRemove) { + releaseLink : function (link) { if (linksCount > 0) { linksCount -= 1; } + var linkUI = allLinks[link.id]; + delete allLinks[link.id]; - linkProgram.removeLink(linkToRemove); + linkProgram.removeLink(linkUI); - var linkIdToRemove = linkToRemove.id; + var linkIdToRemove = linkUI.id; if (linkIdToRemove < linksCount) { if (linksCount === 0 || linksCount === linkIdToRemove) { return; // no more links or removed link is the last one. } - // TODO: consider getting rid of this. The only reason why it's here is to update 'ui' property - // so that renderer will pass proper id in updateLinkPosition. - links[linkIdToRemove] = links[linksCount]; - links[linkIdToRemove].ui.id = linkIdToRemove; + var lastLinkUI = links[linksCount]; + links[linkIdToRemove] = lastLinkUI; + lastLinkUI.id = linkIdToRemove; } }, @@ -6223,61 +6134,67 @@ Viva.Graph.View.webglGraphics = function (options) { * * @param nodeUI visual representation of the node created by node() execution. **/ - releaseNode : function (nodeUI) { + releaseNode : function (node) { if (nodesCount > 0) { nodesCount -= 1; } + var nodeUI = allNodes[node.id]; + delete allNodes[node.id]; nodeProgram.removeNode(nodeUI); - if (nodeUI.id < nodesCount) { - var nodeIdToRemove = nodeUI.id; + var nodeIdToRemove = nodeUI.id; + if (nodeIdToRemove < nodesCount) { if (nodesCount === 0 || nodesCount === nodeIdToRemove) { return; // no more nodes or removed node is the last in the list. } - var lastNode = nodes[nodesCount], - replacedNode = nodes[nodeIdToRemove]; + var lastNodeUI = nodes[nodesCount]; - nodes[nodeIdToRemove] = lastNode; - nodes[nodeIdToRemove].ui.id = nodeIdToRemove; + nodes[nodeIdToRemove] = lastNodeUI; + lastNodeUI.id = nodeIdToRemove; // Since concrete shaders may cache properties in the ui element // we are letting them to make this swap (e.g. image node shader // uses this approach to update node's offset in the atlas) - nodeProgram.replaceProperties(replacedNode.ui, lastNode.ui); + nodeProgram.replaceProperties(nodeUI, lastNodeUI); } }, - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider place given node UI to recommended position pos {x, y}; - */ - updateNodePosition : function (nodeUI, pos) { + renderNodes: function () { + var pos = {x : 0, y : 0}; // WebGL coordinate system is different. Would be better // to have this transform in the shader code, but it would // require every shader to be updated.. - pos.y = -pos.y; - if (userPlaceNodeCallback) { - userPlaceNodeCallback(nodeUI, pos); - } + for (var i = 0; i < nodesCount; ++i) { + var ui = nodes[i]; + pos.x = ui.position.x; + pos.y = -ui.position.y; + if (userPlaceNodeCallback) { + userPlaceNodeCallback(ui, pos); + } - nodeProgram.position(nodeUI, pos); + nodeProgram.position(ui, pos); + } }, - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider place given link of the graph. Pos objects are {x, y}; - */ - updateLinkPosition : function (link, fromPos, toPos) { - // WebGL coordinate system is different. Would be better - // to have this transform in the shader code, but it would - // require every shader to be updated.. - fromPos.y = -fromPos.y; - toPos.y = -toPos.y; - if (userPlaceLinkCallback) { - userPlaceLinkCallback(link, fromPos, toPos); - } + renderLinks: function () { + if (this.omitLinksRendering) { return; } + + var toPos = {x : 0, y : 0}; + var fromPos = {x : 0, y : 0}; + for (var i = 0; i < linksCount; ++i) { + var ui = links[i]; + var pos = ui.pos.from; + fromPos.x = pos.x; + fromPos.y = -pos.y; + pos = ui.pos.to; + toPos.x = pos.x; + toPos.y = -pos.y; + if (userPlaceLinkCallback) { + userPlaceLinkCallback(ui, fromPos, toPos); + } - linkProgram.position(link, fromPos, toPos); + linkProgram.position(ui, fromPos, toPos); + } }, /** @@ -6326,7 +6243,7 @@ Viva.Graph.View.webglGraphics = function (options) { // TODO: unload old shader and reinit. } }, - getGraphCoordinates : function (graphicsRootPos) { + transformClientToGraphCoordinates : function (graphicsRootPos) { // TODO: could be a problem when container has margins? // to save memory we modify incoming parameter: // point in clipspace coordinates: @@ -6340,6 +6257,26 @@ Viva.Graph.View.webglGraphics = function (options) { graphicsRootPos.y *= -height / 2; return graphicsRootPos; + }, + + getNodeAtClientPos: function (clientPos, preciseCheck) { + if (typeof preciseCheck !== "function") { + // we don't know anything about your node structure here :( + // potentially this could be delegated to node program, but for + // right now, we are giving up if you don't pass boundary check + // callback. It answers to a question is nodeUI covers (x, y) + return null; + } + // first transform to graph coordinates: + this.transformClientToGraphCoordinates(clientPos); + // now using precise check iterate over each node and find one within box: + // TODO: This is poor O(N) performance. + for (var i = 0; i < nodesCount; ++i) { + if (preciseCheck(nodes[i], clientPos.x, clientPos.y)) { + return nodes[i].node; + } + } + return null; } }; @@ -6347,22 +6284,22 @@ Viva.Graph.View.webglGraphics = function (options) { Viva.Graph.Utils.events(graphics).extend(); return graphics; -};/** +}; +/** * Monitors graph-related mouse input in webgl graphics and notifies subscribers. * * @param {Viva.Graph.View.webglGraphics} webglGraphics - * @param {Viva.Graph.graph} graph */ -Viva.Graph.webglInputEvents = function (webglGraphics, graph) { +Viva.Graph.webglInputEvents = function (webglGraphics) { if (webglGraphics.webglInputEvents) { // Don't listen twice, if we are already attached to this graphics: return webglGraphics.webglInputEvents; } - var preciseCheck = function (node, x, y) { - if (node.ui && node.ui.size) { - var pos = node.position, - half = node.ui.size; + var preciseCheck = function (nodeUI, x, y) { + if (nodeUI && nodeUI.size) { + var pos = nodeUI.position, + half = nodeUI.size; return pos.x - half < x && x < pos.x + half && pos.y - half < y && y < pos.y + half; @@ -6370,9 +6307,11 @@ Viva.Graph.webglInputEvents = function (webglGraphics, graph) { return true; }, + getNodeAtClientPos = function (pos) { + return webglGraphics.getNodeAtClientPos(pos, preciseCheck); + }, mouseCapturedNode = null, - spatialIndex = Viva.Graph.spatialIndex(graph, preciseCheck), mouseEnterCallback = [], mouseLeaveCallback = [], mouseDownCallback = [], @@ -6441,8 +6380,7 @@ Viva.Graph.webglInputEvents = function (webglGraphics, graph) { pos.x = e.clientX - boundRect.left; pos.y = e.clientY - boundRect.top; - webglGraphics.getGraphCoordinates(pos); - node = spatialIndex.getNodeAt(pos.x, pos.y); + node = getNodeAtClientPos(pos); if (node && lastFound !== node) { lastFound = node; @@ -6462,9 +6400,8 @@ Viva.Graph.webglInputEvents = function (webglGraphics, graph) { pos.x = e.clientX - boundRect.left; pos.y = e.clientY - boundRect.top; - webglGraphics.getGraphCoordinates(pos); - args = [spatialIndex.getNodeAt(pos.x, pos.y), e]; + args = [getNodeAtClientPos(pos), e]; if (args[0]) { cancelBubble = invoke(mouseDownCallback, args); // we clicked on a node. Following drag should be handled on document events: @@ -6489,9 +6426,8 @@ Viva.Graph.webglInputEvents = function (webglGraphics, graph) { pos.x = e.clientX - boundRect.left; pos.y = e.clientY - boundRect.top; - webglGraphics.getGraphCoordinates(pos); - args = [spatialIndex.getNodeAt(pos.x, pos.y), e]; + args = [getNodeAtClientPos(pos), e]; if (args[0]) { window.document.onselectstart = prevSelectStart; @@ -6572,7 +6508,7 @@ Viva.Graph.webglInputEvents = function (webglGraphics, graph) { Viva.Input = Viva.Input || {}; Viva.Input.webglInputManager = function (graph, graphics) { - var inputEvents = Viva.Graph.webglInputEvents(graphics, graph), + var inputEvents = Viva.Graph.webglInputEvents(graphics), draggedNode = null, internalHandlers = {}, pos = {x : 0, y : 0}; @@ -6584,7 +6520,7 @@ Viva.Input.webglInputManager = function (graph, graphics) { inputEvents.mouseCapture(draggedNode); - var handlers = internalHandlers[node.ui.id]; + var handlers = internalHandlers[node.id]; if (handlers && handlers.onStart) { handlers.onStart(e, pos); } @@ -6594,14 +6530,14 @@ Viva.Input.webglInputManager = function (graph, graphics) { inputEvents.releaseMouseCapture(draggedNode); draggedNode = null; - var handlers = internalHandlers[node.ui.id]; + var handlers = internalHandlers[node.id]; if (handlers && handlers.onStop) { handlers.onStop(); } return true; }).mouseMove(function (node, e) { if (draggedNode) { - var handlers = internalHandlers[draggedNode.ui.id]; + var handlers = internalHandlers[draggedNode.id]; if (handlers && handlers.onDrag) { handlers.onDrag(e, {x : e.clientX - pos.x, y : e.clientY - pos.y }); } @@ -6625,7 +6561,10 @@ Viva.Input.webglInputManager = function (graph, graphics) { * onStop: function() */ bindDragNDrop : function (node, handlers) { - internalHandlers[node.ui.id] = handlers; + internalHandlers[node.id] = handlers; + if (!handlers) { + delete internalHandlers[node.id]; + } } }; }; diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 66e5381..470ef6b 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.4.1",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){function e(){var e=4022871197,t=function(t){var n;for(t=""+t,n=0;t.length>n;n++){e+=t.charCodeAt(n);var r=.02519603282416938*e;e=r>>>0,r-=e,r*=e,e=r>>>0,r-=e,e+=4294967296*r}return 2.3283064365386963e-10*(e>>>0)};return t.version="Mash 0.9",t}function t(t){return function(t){var n,r,i=0,o=58,a=119,u=178,s=[],c=e();for(0===t.length&&(t=[+new Date]),n=0;256>n;n++)s[n]=c(" "),s[n]-=4.76837158203125e-7*c(" "),0>s[n]&&(s[n]+=1);for(r=0;t.length>r;r++)for(n=0;256>n;n++)s[n]-=c(t[r]),s[n]-=4.76837158203125e-7*c(t[r]),0>s[n]&&(s[n]+=1);c=null;var f=function(){var e;return i=255&i+1,o=255&o+1,a=255&a+1,u=255&u+1,e=s[i]-s[o],0>e&&(e+=1),e-=s[a],0>e&&(e+=1),e-=s[u],0>e&&(e+=1),s[i]=e,e};return f.uint32=function(){return 4294967296*f()>>>0},f.fract53=f,f.version="LFIB4 0.9",f.args=t,f}(t)}var n=new t(Array.prototype.slice.call(arguments));return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),c=Viva.Graph.Utils.events(e),f=Viva.Graph.Utils.findElementPosition,l=0,d=0,h=!1,p=0,v=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-l,y:r-d}),l=t,d=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},b=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(l=e.clientX,d=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:l,y:d}),s.on("mousemove",w),s.on("mouseup",V),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},V=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",V),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},E=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=v(t),o=f(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},N=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",E,!1):e.addEventListener("DOMMouseScroll",E,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",E,!1):e.removeEventListener("DOMMouseScroll",E,!1)),i=t},P=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=P(e.touches[0],e.touches[1]),r=0;p>n?r=-1:n>p&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),p=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),l=n.clientX,d=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:l,y:d}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),p=P(t.touches[0],t.touches[1])),void 0)};return c.on("mousedown",b),c.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",b),s.stop("mouseup",V),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),N(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.spatialIndex=function(e,t){var n,r,i=16;return"function"==typeof t?(r=t,n=function(t,n){var i=null;return e.forEachNode(function(e){return r(e,t,n)?(i=e,!0):void 0}),i}):"number"==typeof t&&(i=t,n=function(t,n){var r=null;return e.forEachNode(function(e){var o=e.position;return t>o.x-i&&o.x+i>t&&n>o.y-i&&o.y+i>n?(r=e,!0):void 0}),r}),{getNodeAt:n}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,c,f,l,d,h,p,v,m,g,y,x,w,b={x:0,y:0};return s=r-t,f=e-n,d=n*t-e*r,m=s*i+f*o+d,g=s*a+f*u+d,0!==m&&0!==g&&m>=0==g>=4?null:(c=u-o,l=i-a,h=a*o-i*u,p=c*e+l*t+h,v=c*n+l*r+h,0!==p&&0!==v&&p>=0==v>=0?null:(y=s*l-c*f,0===y?null:(x=0>y?-y/2:y/2,x=0,w=f*h-l*d,b.x=(0>w?w-x:w+x)/y,w=c*d-s*h,b.y=(0>w?w-x:w+x)/y,b)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,c=a.y-e.y,f=s*s+c*c;for(r=1;o.length>r;++r){a=o[r];var l=i(a);l===u?(s=a.x-e.x,c=a.y-e.y,n=s*s+c*c,f>n?o.splice(r,1):o.splice(r-1,1)):u=l}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},c=function(e,t){o.push({node:e,changeType:t})},f=function(e,t){o.push({link:e,changeType:t})},l=function(e){return e&&"object"==typeof e&&"number"==typeof e.length&&"function"==typeof e.splice&&!e.propertyIsEnumerable("length")},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);if(i?c(i,"update"):(i=new Viva.Graph.Node(t),r++,c(i,"add")),n){var o,a=i.data||{},f=typeof n;if("string"===f||l(n)||"number"===f||"boolean"===f)a=n;else if("undefined"===f)a=null;else for(o in n)n.hasOwnProperty(o)&&(a[o]=n[o]);i.data=a}return e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),c=""+e+(""+r),l=n.hasOwnProperty(c);(l||this.hasLink(e,r))&&(l||(n[c]=0),c+="@"+ ++n[c]);var d=new Viva.Graph.Link(e,r,i,c);return t.push(d),o.links.push(d),a.links.push(d),f(d,"add"),s(this),d},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),f(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,c(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n;if("function"==typeof e)for(n=0;t.length>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var c=u.velocity.x,f=u.velocity.y,l=Math.sqrt(c*c+f*f);l>r&&(u.velocity.x=r*c/l,u.velocity.y=r*f/l),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},c=[],f=0,l=function(){var e;return c[f]?(e=c[f],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,c[f]=e),++f,e},d=l(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return.01>n&&.01>r},p=function(e){for(o.reset(),o.push(d,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,c=n.left,f=(n.right+c)/2,p=n.top,v=(n.bottom+p)/2;if(i>f){s+=1;var m=c;c=f,f+=f-m}if(a>v){s+=2;var g=p;p=v,v+=v-g}var y=n.quads[s];y||(y=l(),y.left=c,y.top=p,y.right=f,y.bottom=v,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){var w,b;do{var V=2*u.nextDouble()*Math.PI,E=.006*(n.right-n.left)*Math.cos(V),N=.006*(n.bottom-n.top)*Math.sin(V);w=x.location.x+E,b=x.location.y+N}while(n.left>w||w>n.right||n.top>b||b>n.bottom);x.location.x=w,x.location.y=b}o.push(n,x),o.push(n,r)}else n.body=r}},v=function(e){var t,n,o,s,c=i,f=1,l=0,h=1;for(c[0]=d;f;){var p=c[l],v=p.body;f-=1,l+=1,v&&v!==e?(n=v.location.x-e.location.x,o=v.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=p.massX/p.mass-e.location.x,o=p.massY/p.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(p.right-p.left)/s?(t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(p.quads[0]&&(c[h]=p.quads[0],f+=1,h+=1),p.quads[1]&&(c[h]=p.quads[1],f+=1,h+=1),p.quads[2]&&(c[h]=p.quads[2],f+=1,h+=1),p.quads[3]&&(c[h]=p.quads[3],f+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,c=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>c&&(r=c),c>o&&(o=c)}var h=i-n,v=o-r;for(h>v?o=r+h:i=n+v,f=0,d=l(),d.left=n,d.right=i,d.top=r,d.bottom=o,t=u;t--;)p(a[t],d)};return{insert:p,init:m,update:v,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{init:function(){},update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{init:function(){},update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var c=s-o,f=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*c/s*n.weight;r.force.x+=f*a,r.force.y+=f*u,i.force.x+=-f*a,i.force.y+=-f*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t=e,n=[],r=[],i=[],o=[];return{speedLimit:1,bodies:n,accumulate:function(){var e,t,a;for(e=i.length;e--;)i[e].init(this);for(e=o.length;e--;)o[e].init(this);for(e=n.length;e--;)for(a=n[e],a.force.x=0,a.force.y=0,t=0;i.length>t;t++)i[t].update(a);for(e=0;r.length>e;++e)for(t=0;o.length>t;t++)o[t].update(r[e])},run:function(e){return this.accumulate(),t.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return n.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,n);return 0>t?!1:n.splice(t,1)},addSpring:function(e,t,n,i,o){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};o="number"==typeof o?o:1;var a=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,o);return r.push(a),a},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,r);return 0>t?!1:r.splice(t,1)},addBodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};i.push(e)},addSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};o.push(e)}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{compatible:!1,springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),c=function(n){var r=(u.x1+u.x2)/2,i=(u.y1+u.y2)/2,o=t.springLength;if(n.links&&n.links.length>0){var a=n.links[0],c=a.fromId!==n.id?e.getNode(a.fromId):e.getNode(a.toId);c.position&&(r=c.position.x,i=c.position.y)}return{x:r+s.next(o)-o/2,y:i+s.next(o)-o/2}},f={},l=function(e){return f[e]},d=function(e){f[e.id]=null,delete f[e.id]},h={},p=function(t){var n=l(t.id);n.mass=1+e.getLinks(t.id).length/3},v=function(e){var n=l(e.id);if(!n){n=new Viva.Graph.Physics.Body,f[e.id]=n;var i=c(n);n.loc(i),p(e),t.compatible&&(e.position=i,e.force_directed_body=n),r.addBody(n)}},m=function(e){var n=l(e.id);n&&(t.compatible&&(e.force_directed_body=null,delete e.force_directed_body),d(e),r.removeBody(n))},g=function(n){var i=e.getNode(n.fromId),o=e.getNode(n.toId);p(i),p(o);var a=l(n.fromId),u=l(n.toId),s=r.addSpring(a,u,-1,n.weight);h[n.id]=s,t.compatible&&(n.force_directed_spring=s)},y=function(n){var i=h[n.id];if(i){var o=e.getNode(n.fromId),a=e.getNode(n.toId);o&&p(o),a&&p(a),t.compatible&&(n.force_directed_spring=null,delete n.force_directed_spring),delete h[n.id],r.removeSpring(i)}},x=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&v(n.node),n.link&&g(n.link)):"remove"===n.changeType&&(n.node&&m(n.node),n.link&&y(n.link))}},w=function(){e.forEachNode(v),e.forEachLink(g),e.addEventListener("changed",x)},b=function(e,t){return e||t?e&&(e.isPinned||e.data&&e.data.isPinned)||t&&t.isPinned:!0},V=function(){var n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var a in f)if(f.hasOwnProperty(a)){var s=f[a];b(null,s)?(s.location.x=s.prevLocation.x,s.location.y=s.prevLocation.y):(s.prevLocation.x=s.location.x,s.prevLocation.y=s.location.y),n>s.location.x&&(n=s.location.x),s.location.x>i&&(i=s.location.x),r>s.location.y&&(r=s.location.y),s.location.y>o&&(o=s.location.y)}t.compatible&&e.forEachNode(function(e){var t=e.force_directed_body;t&&(e.position.x=t.location.x,e.position.y=t.location.y)}),u.x1=n,u.x2=i,u.y1=r,u.y2=o}};return r.addSpringForce(o),r.addBodyForce(i),r.addBodyForce(a),w(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(20);return V(),n>e},isNodePinned:function(e){var t=l(e.id);return b(e,t)},pinNode:function(e,t){var n=l(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=l(e);return t&&t.location},setNodePosition:function(e,t,n){var r=l(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",x)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.position.xt.x2&&(t.x2=e.position.x),e.position.yt.y2&&(t.y2=e.position.y)},a=function(e){e.hasOwnProperty("position")||(e.position=i(e)),o(e,r)},u=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(a))},s=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&a(n.node)}};return{run:function(){this.step()},step:function(){return u(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",s)},placeNode:function(e){return"function"==typeof e?(i=e,u(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,c=t.container,f=!1,l=!0,d=0,h=0,p=!1,v=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){c=c||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:c}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.compatible=t.compatible||!1,t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x={x:0,y:0,node:null},w={x:0,y:0,node:null},b={x:0,y:0},V=Viva.Graph.Utils.events(window),E=Viva.Graph.Utils.events({}).extend(),N=function(e){var t=u.getNodePosition(e.fromId),n=u.getNodePosition(e.toId);t&&n&&(x.x=t.x,x.y=t.y,w.x=n.x,w.y=n.y,s.updateLinkPosition(e,x,w))},P=function(e){var t=u.getNodePosition(e.id);b.x=t.x,b.y=t.y,s.updateNodePosition(e,b)},G=function(){s.beginRender(),t.renderLinks&&!s.omitLinksRendering&&e.forEachLink(N),e.forEachNode(P),s.endRender()},L=function(){return p=u.step()&&!v,G(),!p},_=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return L()},n)):(d=0,h=0,i=Viva.Graph.Utils.timer(L,n)),void 0)},A=function(){p=!1,i.restart()},I=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},k=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(c);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),l=!1},T=function(e){var n=s.addNode(e);t.compatible&&(e.ui=n),P(e)},C=function(e){s.releaseNode(e),t.compatible&&e.hasOwnProperty("ui")&&(e.ui=null,delete e.ui)},M=function(e){var n=s.addLink(e);t.compatible&&(e.ui=n),s.omitLinksRendering||N(e)},S=function(e){s.releaseLink(e),t.compatible&&e.hasOwnProperty("ui")&&(e.ui=null,delete e.ui)},U=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),v=!0,A()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),v=!0,G()},onStop:function(){u.pinNode(e,t),v=!1}})},R=function(e){r.bindDragNDrop(e,null)},D=function(){s.init(c),e.forEachNode(T),t.renderLinks&&e.forEachLink(M)},F=function(){s.release(c)},O=function(t){var n=t.node;"add"===t.changeType?(T(n),U(n),l&&k()):"remove"===t.changeType?(R(n),C(n),0===e.getNodesCount()&&(l=!0)):"update"===t.changeType&&(R(n),C(n),T(n),U(n))},z=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&M(n);else if("remove"===e.changeType)t.renderLinks&&S(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},B=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?O(n):n.link&&z(n);A()},Y=function(){k(),L()},X=function(){a&&(a.release(),a=null)},q=function(){o&&(o.stop("changed",B),o=null)},W=function(){V.on("resize",Y),X(),a=Viva.Graph.Utils.dragndrop(c),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),G()}),a.onScroll(function(e,t,n){var r=Math.pow(1.4,0>t?-.2:.2);g.scale=s.scale(r,n),G(),E.fire("scale",g.scale)}),e.forEachNode(U),q(),o=Viva.Graph.Utils.events(e),o.on("changed",B)},j=function(){f=!1,q(),X(),V.stop("resize",Y),E.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&S(e)}),e.forEachNode(function(e){R(e),C(e)}),u.dispose(),F()};return{run:function(e){return f||(y(),I(),k(),D(),W(),f=!0),_(e),this},reset:function(){s.resetScale(),k(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return G(),this},dispose:function(){j()},on:function(e,t){return E.addEventListener(e,t),this},off:function(e,t){return E.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var c=n(u.nodes[a]);if(!c.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(c.id,c.data)}for(a=0;u.links.length>a;++a){var f=o(u.links[a]);if(!f.hasOwnProperty("fromId")||!f.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(f.fromId,f.toId,f.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},c={},f=[t.id],l=function(e){c.hasOwnProperty(e.id)||(f.push(e.id),c[e.id]=i+1),c[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),c[t.id]=0,s[t.id]=1;f.length;)r=f.shift(),i=c[r],o=s[r],u.push(r),e.forEachLinkedNode(r,l,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},c=t.S;for(r=0;c.length>r;r+=1)s[c[r]]=0;for(;c.length;){for(i=c.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1; -return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},c=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},f=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},l=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},d=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?l(e):(l=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,d()},translateRel:function(e,r){t+=e,n+=r,d()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return c=e,this},placeLink:function(e){return f=e,this},init:function(t){e=t,d()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){c(e,t)},updateLinkPosition:function(e,t,n){f(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var c=r.childNodes[t];if(1===c.nodeType){var f=c.attr("class"),l=c.attr("id"),d=c.nodeName;if(a&&f){for(f=f.replace(/\s+/g," ").split(" "),n=0;f.length>n;n++)if(a&&f[n]===e.substr(1)){i.push(Viva.Graph.svg(c));break}}else{if(u&&l===e.substr(1)){i.push(Viva.Graph.svg(c));break}s&&d===e&&i.push(Viva.Graph.svg(c))}i=i.concat(Viva.Graph.svg(c).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i=1,o={},a={},u=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},s=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},c=function(){return Viva.Graph.svg("line").attr("stroke","#999")},f=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},l=function(e){e.fire("rescaled")},d=function(){if(e){var t="matrix("+i+", 0, 0,"+i+","+n+","+r+")";e.attr("transform",t)}},h={getNodeUI:function(e){return o[e]},getLinkUI:function(e){return a[e]},node:function(e){return"function"==typeof e?(u=e,this):void 0},link:function(e){return"function"==typeof e?(c=e,this):void 0},placeNode:function(e){return s=e,this},placeLink:function(e){return f=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,d()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(o,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(o).translate(-u.x,-u.y),c=e.getCTM().multiply(s);i=c.a,n=c.e,r=c.f;var f="matrix("+c.a+", 0, 0,"+c.d+","+c.e+","+c.f+")";return e.attr("transform",f),l(this),i},resetScale:function(){i=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),l(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),d()},release:function(e){t&&e&&e.removeChild(t)},addLink:function(t){var n=c(t);if(n)return a[t.id]=n,e.childElementCount>0?e.insertBefore(n,e.firstChild):e.appendChild(n),n},releaseLink:function(t){var n=this.getLinkUI(t);e.removeChild(n)},addNode:function(t){var n=u(t);if(n)return o[t.id]=n,e.appendChild(n),n},releaseNode:function(t){var n=this.getNodeUI(t.id);n&&e.removeChild(n)},updateNodePosition:function(e,t){var n=this.getNodeUI(e.id);n&&s(n,t,e)},updateLinkPosition:function(e,t,n){var r=this.getLinkUI(e.id);f(r,t,n,e)},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(h).extend(),h},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),c=e.position,f=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,c.x,c.y)||r,l=n.intersectRect(c.x-s.w/2,c.y-s.h/2,c.x+s.w/2,c.y+s.h/2,c.x,c.y,r.x,r.y)||c;o+="M"+Math.round(f.x)+" "+Math.round(f.y)+"L"+Math.round(l.x)+" "+Math.round(l.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,c=4,f=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),d=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*f),p=new Float32Array(h),v=new Uint32Array(h),m=0,g=function(){if((m+1)*f>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(v),p=t,v=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(d,l),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;p[n*c]=t.x,p[n*c+1]=t.y,p[n*c+2]=e.size,v[n*c+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(v,e.id*c,m*c,c)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,c*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,c*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,c,f=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),p=0,v=new ArrayBuffer(16*l),m=new Float32Array(v),g=new Uint32Array(v),y=function(){if((p+1)*l>v.byteLength){var e=new ArrayBuffer(2*v.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,v=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,d),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*f;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),p+=1,o=e.id},removeLink:function(e){p>0&&(p-=1),p>e.id&&p>0&&r.copyArrayPart(g,e.id*f,p*f,f)},updateTransform:function(e){c=!0,s=e},updateSize:function(e,t){a=e,u=t,c=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,v,t.DYNAMIC_DRAW),c&&(c=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*p),o=p-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*f,o*f,f),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],c=[],f=function(e){return 0===(e&e-1)},l=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},d=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},p=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},v=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=d(e),o={offset:e};r.textureNumber>=s.length&&l();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),c[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!f(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=d(t.offset),r=d(o);v(r,n);var i=a[c[o]];return i.offset=t.offset,c[t.offset]=c[o],p(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){p(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,c,f=18,l=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),d=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,p=0,v=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(d,l),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*f;v[n]=t.x-e.size,v[n+1]=t.y-e.size,v[n+2]=4*e._offset,v[n+3]=t.x+e.size,v[n+4]=t.y-e.size,v[n+5]=4*e._offset+1,v[n+6]=t.x-e.size,v[n+7]=t.y+e.size,v[n+8]=4*e._offset+2,v[n+9]=t.x-e.size,v[n+10]=t.y+e.size,v[n+11]=4*e._offset+2,v[n+12]=t.x+e.size,v[n+13]=t.y-e.size,v[n+14]=4*e._offset+1,v[n+15]=t.x+e.size,v[n+16]=t.y+e.size,v[n+17]=4*e._offset+3},createNode:function(t){v=i.extendArray(v,p,f),p+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){p>0&&(p-=1),p>t.id&&p>0&&(t.src&&e.remove(t.src),i.copyArrayPart(v,t.id*f,p*f,f))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){c=!0,s=e},updateSize:function(e,t){a=e,u=t,c=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,v,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*p)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,c,f=0,l=0,d=[],h=[],p=Viva.Graph.View.webglLinkProgram(),v=Viva.Graph.View.webglNodeProgram(),m=function(){return Viva.Graph.View.webglSquare()},g=function(){return Viva.Graph.View.webglLine(3014898687)},y=function(){p.updateTransform(a),v.updateTransform(a)},x=function(){a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},w=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),p&&p.updateSize(i/2,o/2),v&&v.updateSize(i/2,o/2))},b=function(e){var t=f++,n=m(e);return n.id=t,v.createNode(n),d[t]=e,n},V=function(e){var t=l++,n=g(e);return n.id=t,p.createLink(n),h[t]=e,n},E=function(e){e.fire("rescaled")},N={node:function(e){return e&&"function"!=typeof e?b(e):(m=e,this)},link:function(e){return e&&"function"!=typeof e?V(e):(g=e,this)},placeNode:function(e){return u=e,this},placeLink:function(e){return s=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){l>0&&p.render(),f>0&&v.render()},bringLinkToFront:function(e){var t,n,r=p.getFrontLinkId();p.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].ui.id=r,h[t]=n,h[t].ui.id=t)},graphCenterChanged:function(){w()},initLink:function(){},initNode:function(){},translateRel:function(e,t){a[12]+=2*a[0]*e/i/a[0],a[13]-=2*a[5]*t/o/a[5],y()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=a[12],r-=a[13],a[12]+=n*(1-e),a[13]+=r*(1-e),a[0]*=e,a[5]*=e,y(),E(this),a[0]},resetScale:function(){return x(),r&&(w(),y()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),w(),x(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var s="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(s),s}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var f=e.clearColorValue;r.clearColor(f.r,f.g,f.b,f.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}p.load(r),p.updateSize(i/2,o/2),v.load(r),v.updateSize(i/2,o/2),y(),"function"==typeof c&&c(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){l>0&&(l-=1),p.removeLink(e);var t=e.id;if(l>t){if(0===l||l===t)return;h[t]=h[l],h[t].ui.id=t}},releaseNode:function(e){if(f>0&&(f-=1),v.removeNode(e),f>e.id){var t=e.id;if(0===f||f===t)return;var n=d[f],r=d[t];d[t]=n,d[t].ui.id=t,v.replaceProperties(r.ui,n.ui)}},updateNodePosition:function(e,t){t.y=-t.y,u&&u(e,t),v.position(e,t)},updateLinkPosition:function(e,t,n){t.y=-t.y,n.y=-n.y,s&&s(e,t,n),p.position(e,t,n)},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):c=e),n},setNodeProgram:function(e){if(!r&&e)v=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)p=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},getGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-a[12])/a[0],e.y=(e.y-a[13])/a[5],e.x*=i/2,e.y*=-o/2,e}};return Viva.Graph.Utils.events(N).extend(),N},Viva.Graph.webglInputEvents=function(e,t){if(e.webglInputEvents)return e.webglInputEvents;var n,r,i=function(e,t,n){if(e.ui&&e.ui.size){var r=e.position,i=e.ui.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},o=null,a=Viva.Graph.spatialIndex(t,i),u=[],s=[],c=[],f=[],l=[],d=[],h=[],p=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},m=function(e){return v(e),!1},g=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},y=function(t){var i={x:0,y:0},y=null,x=+new Date,w=function(e){g(l,[y,e]),i.x=e.clientX,i.y=e.clientY},b=function(){p.stop("mousemove",w),p.stop("mouseup",b)},V=function(){r=t.getBoundingClientRect()};window.addEventListener("resize",V),V(),t.addEventListener("mousemove",function(t){if(!o){var n,c=!1;i.x=t.clientX-r.left,i.y=t.clientY-r.top,e.getGraphCoordinates(i),n=a.getNodeAt(i.x,i.y),n&&y!==n?(y=n,c=c||g(u,[y])):null===n&&y!==n&&(c=c||g(s,[y]),y=null),c&&v(t)}}),t.addEventListener("mousedown",function(t){var o,u=!1;i.x=t.clientX-r.left,i.y=t.clientY-r.top,e.getGraphCoordinates(i),o=[a.getNodeAt(i.x,i.y),t],o[0]?(u=g(c,o),p.on("mousemove",w),p.on("mouseup",b),n=window.document.onselectstart,window.document.onselectstart=m,y=o[0]):y=null,u&&v(t)}),t.addEventListener("mouseup",function(t){var o,u=+new Date;i.x=t.clientX-r.left,i.y=t.clientY-r.top,e.getGraphCoordinates(i),o=[a.getNodeAt(i.x,i.y),t],o[0]&&(window.document.onselectstart=n,400>u-x&&o[0]===y?g(h,o):g(d,o),x=u,g(f,o)&&v(t))})};return e.getGraphicsRoot(y),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&u.push(e),this},mouseLeave:function(e){return"function"==typeof e&&s.push(e),this},mouseDown:function(e){return"function"==typeof e&&c.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&l.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&h.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t,e),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.ui.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.ui.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.ui.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.ui.id]=t}}}; \ No newline at end of file +var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.0",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){function e(){var e=4022871197,t=function(t){var n;for(t=""+t,n=0;t.length>n;n++){e+=t.charCodeAt(n);var r=.02519603282416938*e;e=r>>>0,r-=e,r*=e,e=r>>>0,r-=e,e+=4294967296*r}return 2.3283064365386963e-10*(e>>>0)};return t.version="Mash 0.9",t}function t(t){return function(t){var n,r,i=0,o=58,a=119,u=178,s=[],f=e();for(0===t.length&&(t=[+new Date]),n=0;256>n;n++)s[n]=f(" "),s[n]-=4.76837158203125e-7*f(" "),0>s[n]&&(s[n]+=1);for(r=0;t.length>r;r++)for(n=0;256>n;n++)s[n]-=f(t[r]),s[n]-=4.76837158203125e-7*f(t[r]),0>s[n]&&(s[n]+=1);f=null;var c=function(){var e;return i=255&i+1,o=255&o+1,a=255&a+1,u=255&u+1,e=s[i]-s[o],0>e&&(e+=1),e-=s[a],0>e&&(e+=1),e-=s[u],0>e&&(e+=1),s[i]=e,e};return c.uint32=function(){return 4294967296*c()>>>0},c.fract53=c,c.version="LFIB4 0.9",c.args=t,c}(t)}var n=new t(Array.prototype.slice.call(arguments));return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,l=0,d=0,h=!1,p=0,v=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-l,y:r-d}),l=t,d=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(l=e.clientX,d=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:l,y:d}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},P=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=v(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},E=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",P,!1):e.addEventListener("DOMMouseScroll",P,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",P,!1):e.removeEventListener("DOMMouseScroll",P,!1)),i=t},N=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=N(e.touches[0],e.touches[1]),r=0;p>n?r=-1:n>p&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),p=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),l=n.clientX,d=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:l,y:d}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),p=N(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return E(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),E(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,l,d,h,p,v,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,d=n*t-e*r,m=s*i+c*o+d,g=s*a+c*u+d,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,l=i-a,h=a*o-i*u,p=f*e+l*t+h,v=f*n+l*r+h,0!==p&&0!==v&&p>=0==v>=0?null:(y=s*l-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-l*d,V.x=(0>w?w-x:w+x)/y,w=f*d-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var l=i(a);l===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=l}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},l=function(e){return e&&"object"==typeof e&&"number"==typeof e.length&&"function"==typeof e.splice&&!e.propertyIsEnumerable("length")},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);if(i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),n){var o,a=i.data||{},c=typeof n;if("string"===c||l(n)||"number"===c||"boolean"===c)a=n;else if("undefined"===c)a=null;else for(o in n)n.hasOwnProperty(o)&&(a[o]=n[o]);i.data=a}return e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),l=n.hasOwnProperty(f);(l||this.hasLink(e,r))&&(l||(n[f]=0),f+="@"+ ++n[f]);var d=new Viva.Graph.Link(e,r,i,f);return t.push(d),o.links.push(d),a.links.push(d),c(d,"add"),s(this),d},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,l=Math.sqrt(f*f+c*c);l>r&&(u.velocity.x=r*f/l,u.velocity.y=r*c/l),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,l=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},d=l(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},p=function(e){for(o.reset(),o.push(d,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,p=n.top,v=(n.bottom+p)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>v){s+=2;var g=p;p=v,v+=v-g}var y=n.quads[s];y||(y=l(),y.left=f,y.top=p,y.right=c,y.bottom=v,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},v=function(e){var t,n,o,s,f=i,c=1,l=0,h=1;for(f[0]=d;c;){var p=f[l],v=p.body;c-=1,l+=1,v&&v!==e?(n=v.location.x-e.location.x,o=v.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=p.massX/p.mass-e.location.x,o=p.massY/p.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(p.right-p.left)/s?(t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(p.quads[0]&&(f[h]=p.quads[0],c+=1,h+=1),p.quads[1]&&(f[h]=p.quads[1],c+=1,h+=1),p.quads[2]&&(f[h]=p.quads[2],c+=1,h+=1),p.quads[3]&&(f[h]=p.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,v=o-r;for(h>v?o=r+h:i=n+v,c=0,d=l(),d.left=n,d.right=i,d.top=r,d.bottom=o,t=u;t--;)p(a[t],d)};return{insert:p,init:m,update:v,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};i="number"==typeof i?i:1;var o=new Viva.Graph.Physics.Spring(e,t,n,r>=0?r:-1,i);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),f={},c=function(e){var n=(u.x1+u.x2)/2,r=(u.y1+u.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],a=o.fromId!==e.id?f[o.fromId]:f[o.toId];a&&a.location&&(n=a.location.x,r=a.location.y)}return{x:n+s.next(i)-i/2,y:r+s.next(i)-i/2}},l=function(e){return f[e]},d=function(e){f[e.id]=null,delete f[e.id]},h={},p=function(t){var n=l(t.id);n.mass=1+e.getLinks(t.id).length/3},v=function(e,t){return e||t?e&&(e.isPinned||e.data&&e.data.isPinned)||t&&t.isPinned:!0},m=function(e){var t=l(e.id);if(!t){t=new Viva.Graph.Physics.Body,f[e.id]=t;var n=c(e);t.loc(n),p(e),v(e)&&(t.isPinned=!0),r.addBody(t)}},g=function(e){var t=l(e.id);t&&(d(e),r.removeBody(t))},y=function(t){var n=e.getNode(t.fromId),i=e.getNode(t.toId);p(n),p(i);var o=l(t.fromId),a=l(t.toId),u=r.addSpring(o,a,-1,t.weight);h[t.id]=u},x=function(t){var n=h[t.id];if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&p(i),o&&p(o),delete h[t.id],r.removeSpring(n)}},w=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&m(n.node),n.link&&y(n.link)):"remove"===n.changeType&&(n.node&&g(n.node),n.link&&x(n.link))}},V=function(){e.forEachNode(m),e.forEachLink(y),e.addEventListener("changed",w)},b=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in f)if(f.hasOwnProperty(o)){var a=f[o];v(null,a)?(a.location.x=a.prevLocation.x,a.location.y=a.prevLocation.y):(a.prevLocation.x=a.location.x,a.prevLocation.y=a.location.y),t>a.location.x&&(t=a.location.x),a.location.x>r&&(r=a.location.x),n>a.location.y&&(n=a.location.y),a.location.y>i&&(i=a.location.y)}u.x1=t,u.x2=r,u.y1=n,u.y2=i}};return r.setSpringForce(o),r.setNbodyForce(i),r.setDragForce(a),V(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(20);return b(),n>e},isNodePinned:function(e){var t=l(e.id);return v(e,t)},pinNode:function(e,t){var n=l(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=l(e);return t&&t.location},getBoundNodePosition:function(e){var t=l(e.id);return t||(m(e),t=l(e.id)),t.location},getBoundLinkPosition:function(t){var n=e.getNode(t.fromId),r=e.getNode(t.toId),i=this.getBoundNodePosition(n),o=this.getBoundNodePosition(r);return{from:i,to:o}},setNodePosition:function(e,t,n){var r=l(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",w)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.position.xt.x2&&(t.x2=e.position.x),e.position.yt.y2&&(t.y2=e.position.y)},a=function(e){e.hasOwnProperty("position")||(e.position=i(e)),o(e,r)},u=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(a))},s=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&a(n.node)}};return{run:function(){this.step()},step:function(){return u(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",s)},placeNode:function(e){return"function"==typeof e?(i=e,u(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,l=!0,d=0,h=0,p=!1,v=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return p=u.step()&&!v,V(),!p},P=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(d=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},E=function(){p=!1,i.restart()},N=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),l=!1},L=function(e){var t=u.getBoundNodePosition(e);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getBoundLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),v=!0,E()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),v=!0,V()},onStop:function(){u.pinNode(e,t),v=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),l&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(l=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},R=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);E()},D=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",R),o=null)},z=function(){x.on("resize",D),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){var r=Math.pow(1.4,0>t?-.2:.2);g.scale=s.scale(r,n),V(),w.fire("scale",g.scale)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",R)},B=function(){c=!1,O(),F(),x.stop("resize",D),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),N(),G(),C(),z(),c=!0),P(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},dispose:function(){B()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],l=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,l,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t); +return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},l=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},d=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?l(e):(l=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,d()},translateRel:function(e,r){t+=e,n+=r,d()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,d()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),l=f.attr("id"),d=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&l===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&d===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i,o=1,a={},u={},s=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},f=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},c=function(){return Viva.Graph.svg("line").attr("stroke","#999")},l=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},d=function(e){e.fire("rescaled")},h={x:0,y:0},p={x:0,y:0},v={x:0,y:0},m=function(){if(e){var t="matrix("+o+", 0, 0,"+o+","+n+","+r+")";e.attr("transform",t)}},g={getNodeUI:function(e){return a[e]},getLinkUI:function(e){return u[e]},node:function(e){return"function"==typeof e?(s=e,this):void 0},link:function(e){return"function"==typeof e?(c=e,this):void 0},placeNode:function(e){return f=e,this},placeLink:function(e){return l=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,m()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(i,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(i).translate(-u.x,-u.y),f=e.getCTM().multiply(s);o=f.a,n=f.e,r=f.f;var c="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",c),d(this),o},resetScale:function(){o=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),d(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),m(),"function"==typeof i&&i(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(t,n){var r=c(t);if(r)return r.position=n,r.link=t,u[t.id]=r,e.childElementCount>0?e.insertBefore(r,e.firstChild):e.appendChild(r),r},releaseLink:function(t){var n=u[t.id];n&&(e.removeChild(n),delete u[t.id])},addNode:function(t,n){var r=s(t);if(r)return r.position=n,r.node=t,a[t.id]=r,e.appendChild(r),r},releaseNode:function(t){var n=a[t.id];n&&(e.removeChild(n),delete a[t.id])},renderNodes:function(){for(var e in a)if(a.hasOwnProperty(e)){var t=a[e];h.x=t.position.x,h.y=t.position.y,f(t,h,t.node)}},renderLinks:function(){for(var e in u)if(u.hasOwnProperty(e)){var t=u[e];p.x=t.position.from.x,p.y=t.position.from.y,v.x=t.position.to.x,v.y=t.position.to.y,l(t,p,v,t.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):i=e),t},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(g).extend(),g},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,l=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(l.x)+" "+Math.round(l.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),d=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),p=new Float32Array(h),v=new Uint32Array(h),m=0,g=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(v),p=t,v=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(d,l),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;p[n*f]=t.x,p[n*f+1]=t.y,p[n*f+2]=e.size,v[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(v,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),p=0,v=new ArrayBuffer(16*l),m=new Float32Array(v),g=new Uint32Array(v),y=function(){if((p+1)*l>v.byteLength){var e=new ArrayBuffer(2*v.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,v=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,d),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),p+=1,o=e.id},removeLink:function(e){p>0&&(p-=1),p>e.id&&p>0&&r.copyArrayPart(g,e.id*c,p*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,v,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*p),o=p-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},l=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},d=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},p=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},v=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=d(e),o={offset:e};r.textureNumber>=s.length&&l();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=d(t.offset),r=d(o);v(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],p(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){p(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,l=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),d=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,p=0,v=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(d,l),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;v[n]=t.x-e.size,v[n+1]=t.y-e.size,v[n+2]=4*e._offset,v[n+3]=t.x+e.size,v[n+4]=t.y-e.size,v[n+5]=4*e._offset+1,v[n+6]=t.x-e.size,v[n+7]=t.y+e.size,v[n+8]=4*e._offset+2,v[n+9]=t.x-e.size,v[n+10]=t.y+e.size,v[n+11]=4*e._offset+2,v[n+12]=t.x+e.size,v[n+13]=t.y-e.size,v[n+14]=4*e._offset+1,v[n+15]=t.x+e.size,v[n+16]=t.y+e.size,v[n+17]=4*e._offset+3},createNode:function(t){v=i.extendArray(v,p,c),p+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){p>0&&(p-=1),p>t.id&&p>0&&(t.src&&e.remove(t.src),i.copyArrayPart(v,t.id*c,p*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,v,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*p)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f,c=0,l=0,d=[],h=[],p={},v={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(a),g.updateTransform(a)},V=function(){a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},P=function(e){e.fire("rescaled")},E={getLinkUI:function(e){return v[e]},getNodeUI:function(e){return p[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return u=e,this},placeLink:function(e){return s=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){l>0&&m.render(),c>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(){b()},addLink:function(e,t){var n=l++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,v[e.id]=r,r},addNode:function(e,t){var n=c++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),d[n]=r,p[e.id]=r,r},translateRel:function(e,t){a[12]+=2*a[0]*e/i/a[0],a[13]-=2*a[5]*t/o/a[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=a[12],r-=a[13],a[12]+=n*(1-e),a[13]+=r*(1-e),a[0]*=e,a[5]*=e,w(),P(this),a[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var s="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(s),s}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof f&&f(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){l>0&&(l-=1);var t=v[e.id];delete v[e.id],m.removeLink(t);var n=t.id;if(l>n){if(0===l||l===n)return;var r=h[l];h[n]=r,r.id=n}},releaseNode:function(e){c>0&&(c-=1);var t=p[e.id];delete p[e.id],g.removeNode(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=d[c];d[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;c>t;++t){var n=d[t];e.x=n.position.x,e.y=-n.position.y,u&&u(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;l>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,s&&s(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):f=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-a[12])/a[0],e.y=(e.y-a[13])/a[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;c>n;++n)if(t(d[n],e.x,e.y))return d[n].node;return null}};return Viva.Graph.Utils.events(E).extend(),E},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},i=function(t){return e.getNodeAtClientPos(t,r)},o=null,a=[],u=[],s=[],f=[],c=[],l=[],d=[],h=Viva.Graph.Utils.events(window.document),p=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},v=function(e){return p(e),!1},m=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(e){var r={x:0,y:0},g=null,y=+new Date,x=function(e){m(c,[g,e]),r.x=e.clientX,r.y=e.clientY},w=function(){h.stop("mousemove",x),h.stop("mouseup",w)},V=function(){n=e.getBoundingClientRect()};window.addEventListener("resize",V),V(),e.addEventListener("mousemove",function(e){if(!o){var t,s=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,t=i(r),t&&g!==t?(g=t,s=s||m(a,[g])):null===t&&g!==t&&(s=s||m(u,[g]),g=null),s&&p(e)}}),e.addEventListener("mousedown",function(e){var o,a=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]?(a=m(s,o),h.on("mousemove",x),h.on("mouseup",w),t=window.document.onselectstart,window.document.onselectstart=v,g=o[0]):g=null,a&&p(e)}),e.addEventListener("mouseup",function(e){var o,a=+new Date;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]&&(window.document.onselectstart=t,400>a-y&&o[0]===g?m(d,o):m(l,o),y=a,m(f,o)&&p(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&l.push(e),this},dblClick:function(e){return"function"==typeof e&&d.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file diff --git a/src/version.js b/src/version.js index fc9a685..62c88a4 100644 --- a/src/version.js +++ b/src/version.js @@ -1 +1 @@ -Viva.Graph.version = '0.4.1'; +Viva.Graph.version = '0.5.0'; From f662b64a629f1180440d2891085e0c2aca959c01 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 7 Sep 2013 22:34:40 -0700 Subject: [PATCH 027/276] Updated tutorial to match new design --- .../04 - Listen To Mouse Events.html | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/demos/tutorial_svg/04 - Listen To Mouse Events.html b/demos/tutorial_svg/04 - Listen To Mouse Events.html index b951dbf..723dd3c 100644 --- a/demos/tutorial_svg/04 - Listen To Mouse Events.html +++ b/demos/tutorial_svg/04 - Listen To Mouse Events.html @@ -4,7 +4,7 @@ 04. Listen to mouse events. Vivagraph SVG tutorial. - @@ -25,23 +25,23 @@ highlightRelatedNodes = function(nodeId, isOn) { // just enumerate all realted nodes and update link color: graph.forEachLinkedNode(nodeId, function(node, link){ - if (link && link.ui) { - // link.ui is a special property of each link - // points to the link presentation object. - link.ui.attr('stroke', isOn ? 'red' : 'gray'); + var linkUI = graphics.getLinkUI(link.id); + if (linkUI) { + // linkUI is a UI object created by graphics below + linkUI.attr('stroke', isOn ? 'red' : 'gray'); } }); }; // Since we are using SVG we can easily subscribe to any supported - // events (http://www.w3.org/TR/SVG/interact.html#SVGEvents ), + // events (http://www.w3.org/TR/SVG/interact.html#SVGEvents ), // including mouse events: graphics.node(function(node) { var ui = Viva.Graph.svg('image') .attr('width', nodeSize) .attr('height', nodeSize) - .link('https://secure.gravatar.com/avatar/' + node.data); - + .link('https://secure.gravatar.com/avatar/' + node.data); + $(ui).hover(function() { // mouse over highlightRelatedNodes(node.id, true); }, function() { // mouse out @@ -50,13 +50,13 @@ return ui; }).placeNode(function(nodeUI, pos) { nodeUI.attr('x', pos.x - nodeSize / 2).attr('y', pos.y - nodeSize / 2); - }); + }); graphics.link(function(link){ return Viva.Graph.svg('path') .attr('stroke', 'gray'); }).placeLink(function(linkUI, fromPos, toPos) { - var data = 'M' + fromPos.x + ',' + fromPos.y + + var data = 'M' + fromPos.x + ',' + fromPos.y + 'L' + toPos.x + ',' + toPos.y; linkUI.attr("d", data); @@ -69,7 +69,7 @@ renderer.run(); } - + @@ -77,4 +77,4 @@ - \ No newline at end of file + From 44d8664886808af2e9e8a31e53b2caff03cd21d1 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 7 Sep 2013 22:35:06 -0700 Subject: [PATCH 028/276] Removed unnecessary whitespaces --- demos/tutorial_svg/01 - Create Graph.html | 6 +-- .../tutorial_svg/02 - Create Custom Node.html | 20 +++---- .../tutorial_svg/03 - Create Custom Link.html | 20 +++---- .../tutorial_svg/05 - Edges With Arrows.html | 54 +++++++++---------- demos/tutorial_svg/06 - Composite Nodes.html | 18 +++---- demos/tutorial_svg/07 - Show Dual Links.html | 10 ++-- 6 files changed, 64 insertions(+), 64 deletions(-) diff --git a/demos/tutorial_svg/01 - Create Graph.html b/demos/tutorial_svg/01 - Create Graph.html index f2e5944..c5a87ab 100644 --- a/demos/tutorial_svg/01 - Create Graph.html +++ b/demos/tutorial_svg/01 - Create Graph.html @@ -11,7 +11,7 @@ // Step 2. We add nodes and edges to the graph: graph.addLink(1, 2); - /* Note: graph.addLink() creates new nodes if they are not yet + /* Note: graph.addLink() creates new nodes if they are not yet present in the graph. Thus calling this method is equivalent to: graph.addNode(1); @@ -24,7 +24,7 @@ renderer.run(); } - + @@ -32,4 +32,4 @@ - \ No newline at end of file + diff --git a/demos/tutorial_svg/02 - Create Custom Node.html b/demos/tutorial_svg/02 - Create Custom Node.html index f136628..49dae2e 100644 --- a/demos/tutorial_svg/02 - Create Custom Node.html +++ b/demos/tutorial_svg/02 - Create Custom Node.html @@ -8,9 +8,9 @@ // Step 1. Create a graph: var graph = Viva.Graph.graph(); - // Step 2. Add graph content. - // graph.addNode(nodeId, yourCustomData) method lets you add new - // nodes to the graph and associate them with custom data. In this + // Step 2. Add graph content. + // graph.addNode(nodeId, yourCustomData) method lets you add new + // nodes to the graph and associate them with custom data. In this // case we are associating GitHub user profiles with their Gravatar's images: graph.addNode('anvaka', '91bad8ceeec43ae303790f8fe238164b'); graph.addNode('indexzero', 'd43e8ea63b61e7669ded5b9d3c2e980f'); @@ -26,19 +26,19 @@ // something better than blue dots: graphics.node(function(node) { // node.data holds custom object passed to graph.addNode(): - var url = 'https://secure.gravatar.com/avatar/' + node.data; - + var url = 'https://secure.gravatar.com/avatar/' + node.data; + return Viva.Graph.svg('image') .attr('width', 24) .attr('height', 24) - .link(url); + .link(url); }); - // Usually when you have custom look for nodes, you might want to + // Usually when you have custom look for nodes, you might want to // set their position in a new way too. placeNode() method serves // this goal: graphics.placeNode(function(nodeUI, pos) { - // nodeUI - is exactly the same object that we returned from + // nodeUI - is exactly the same object that we returned from // node() callback above. // pos - is calculated position for this node. nodeUI.attr('x', pos.x - 12).attr('y', pos.y - 12); @@ -51,7 +51,7 @@ renderer.run(); } - + @@ -59,4 +59,4 @@ - \ No newline at end of file + diff --git a/demos/tutorial_svg/03 - Create Custom Link.html b/demos/tutorial_svg/03 - Create Custom Link.html index a9dbcea..39cd630 100644 --- a/demos/tutorial_svg/03 - Create Custom Link.html +++ b/demos/tutorial_svg/03 - Create Custom Link.html @@ -8,7 +8,7 @@ // Step 1. Create a graph: var graph = Viva.Graph.graph(); - // Step 2. Add graph content. + // Step 2. Add graph content. graph.addNode('anvaka', '91bad8ceeec43ae303790f8fe238164b'); graph.addNode('indexzero', 'd43e8ea63b61e7669ded5b9d3c2e980f'); @@ -16,20 +16,20 @@ // Step 3. Customize node appearance. var graphics = Viva.Graph.View.svgGraphics(); - - // Nothing changed in these lines. They are the same as in Step 2 + + // Nothing changed in these lines. They are the same as in Step 2 // of this tutorial. Except maybe chaining support: graphics.node(function(node) { return Viva.Graph.svg('image') .attr('width', 24) .attr('height', 24) - .link('https://secure.gravatar.com/avatar/' + node.data); + .link('https://secure.gravatar.com/avatar/' + node.data); }).placeNode(function(nodeUI, pos) { nodeUI.attr('x', pos.x - 12).attr('y', pos.y - 12); - }); + }); // Step 4. Customize link appearance: - // As you might have guessed already the link()/placeLink() + // As you might have guessed already the link()/placeLink() // functions complement the node()/placeNode() functions // and let us override default presentation of edges: graphics.link(function(link){ @@ -38,10 +38,10 @@ .attr('stroke-dasharray', '5, 5'); }).placeLink(function(linkUI, fromPos, toPos) { // linkUI - is the object returend from link() callback above. - var data = 'M' + fromPos.x + ',' + fromPos.y + + var data = 'M' + fromPos.x + ',' + fromPos.y + 'L' + toPos.x + ',' + toPos.y; - // 'Path data' (http://www.w3.org/TR/SVG/paths.html#DAttribute ) + // 'Path data' (http://www.w3.org/TR/SVG/paths.html#DAttribute ) // is a common way of rendering paths in SVG: linkUI.attr("d", data); }); @@ -53,7 +53,7 @@ renderer.run(); } - + @@ -61,4 +61,4 @@ - \ No newline at end of file + diff --git a/demos/tutorial_svg/05 - Edges With Arrows.html b/demos/tutorial_svg/05 - Edges With Arrows.html index 4e40236..35253fd 100644 --- a/demos/tutorial_svg/05 - Edges With Arrows.html +++ b/demos/tutorial_svg/05 - Edges With Arrows.html @@ -8,35 +8,35 @@ // This demo shows how to create a directional arrow in SVG renderer. // Though it might seem wordy it's due to SVG specific operations. // The library has minimal SVG manipulation support. - // Maybe in future some of the following technniques will become part + // Maybe in future some of the following technniques will become part // of the library itself... var graph = Viva.Graph.graph(); var graphics = Viva.Graph.View.svgGraphics(), nodeSize = 24; - // In this example we fire off renderer before anything is added to + // In this example we fire off renderer before anything is added to // the graph: var renderer = Viva.Graph.View.renderer(graph, { graphics : graphics }); renderer.run(); - + graphics.node(function(node) { return Viva.Graph.svg('image') .attr('width', nodeSize) .attr('height', nodeSize) - .link('https://secure.gravatar.com/avatar/' + node.data); + .link('https://secure.gravatar.com/avatar/' + node.data); }).placeNode(function(nodeUI, pos) { nodeUI.attr('x', pos.x - nodeSize / 2).attr('y', pos.y - nodeSize / 2); - }); + }); + - // To render an arrow we have to address two problems: - // 1. Links should start/stop at node's bounding box, not at the node center. + // 1. Links should start/stop at node's bounding box, not at the node center. // 2. Render an arrow shape at the end of the link. - // Rendering arrow shape is achieved by using SVG markers, part of the SVG + // Rendering arrow shape is achieved by using SVG markers, part of the SVG // standard: http://www.w3.org/TR/SVG/painting.html#Markers var createMarker = function(id) { return Viva.Graph.svg('marker') @@ -49,30 +49,30 @@ .attr('markerHeight', "5") .attr('orient', "auto"); }, - + marker = createMarker('Triangle'); marker.append('path').attr('d', 'M 0 0 L 10 5 L 0 10 z'); - + // Marker should be defined only once in child element of root element: var defs = graphics.getSvgRoot().append('defs'); defs.append(marker); - - var geom = Viva.Graph.geom(); - + + var geom = Viva.Graph.geom(); + graphics.link(function(link){ // Notice the Triangle marker-end attribe: return Viva.Graph.svg('path') .attr('stroke', 'gray') .attr('marker-end', 'url(#Triangle)'); }).placeLink(function(linkUI, fromPos, toPos) { - // Here we should take care about + // Here we should take care about // "Links should start/stop at node's bounding box, not at the node center." - + // For rectangular nodes Viva.Graph.geom() provides efficient way to find // an intersection point between segment and rectangle var toNodeSize = nodeSize, fromNodeSize = nodeSize; - + var from = geom.intersectRect( // rectangle: fromPos.x - fromNodeSize / 2, // left @@ -80,9 +80,9 @@ fromPos.x + fromNodeSize / 2, // right fromPos.y + fromNodeSize / 2, // bottom // segment: - fromPos.x, fromPos.y, toPos.x, toPos.y) + fromPos.x, fromPos.y, toPos.x, toPos.y) || fromPos; // if no intersection found - return center of the node - + var to = geom.intersectRect( // rectangle: toPos.x - toNodeSize / 2, // left @@ -90,12 +90,12 @@ toPos.x + toNodeSize / 2, // right toPos.y + toNodeSize / 2, // bottom // segment: - toPos.x, toPos.y, fromPos.x, fromPos.y) + toPos.x, toPos.y, fromPos.x, fromPos.y) || toPos; // if no intersection found - return center of the node - + var data = 'M' + from.x + ',' + from.y + 'L' + to.x + ',' + to.y; - + linkUI.attr("d", data); }); @@ -103,15 +103,15 @@ graph.addNode('anvaka', '91bad8ceeec43ae303790f8fe238164b'); graph.addNode('indexzero', 'd43e8ea63b61e7669ded5b9d3c2e980f'); graph.addLink('anvaka', 'indexzero'); - - // You might have noticed that the order in which - // we call renderer.run() and graph.addNode()/addLink() differs from + + // You might have noticed that the order in which + // we call renderer.run() and graph.addNode()/addLink() differs from // previous tutorials. The reason for this is that graphics.getSVGRoot() returns - // null if it was not initialized by the renderer yet. Maybe this behavior will + // null if it was not initialized by the renderer yet. Maybe this behavior will // be fixed in future. } - + @@ -119,4 +119,4 @@ - \ No newline at end of file + diff --git a/demos/tutorial_svg/06 - Composite Nodes.html b/demos/tutorial_svg/06 - Composite Nodes.html index b2a0714..4aaf33c 100644 --- a/demos/tutorial_svg/06 - Composite Nodes.html +++ b/demos/tutorial_svg/06 - Composite Nodes.html @@ -6,7 +6,7 @@ - + @@ -54,4 +54,4 @@ - \ No newline at end of file + diff --git a/demos/tutorial_svg/07 - Show Dual Links.html b/demos/tutorial_svg/07 - Show Dual Links.html index a895bef..df3d23b 100644 --- a/demos/tutorial_svg/07 - Show Dual Links.html +++ b/demos/tutorial_svg/07 - Show Dual Links.html @@ -18,7 +18,7 @@ ui = Viva.Graph.svg('path') .attr('stroke', isBuy ? 'red' : 'blue') .attr('fill', 'none'); - + ui.isBuy = isBuy; // remember for future. return ui; @@ -26,10 +26,10 @@ // linkUI - is the object returend from link() callback above. var ry = linkUI.isBuy ? 10 : 0, // using arc command: http://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands - data = 'M' + fromPos.x + ',' + fromPos.y + + data = 'M' + fromPos.x + ',' + fromPos.y + ' A 10,' + ry + ',-30,0,1,' + toPos.x + ',' + toPos.y; - // 'Path data' (http://www.w3.org/TR/SVG/paths.html#DAttribute ) + // 'Path data' (http://www.w3.org/TR/SVG/paths.html#DAttribute ) // is a common way of rendering paths in SVG: linkUI.attr("d", data); }); @@ -37,11 +37,11 @@ renderer.run(); } - - \ No newline at end of file + From 5a416912861f3b1375ac21542cb1c066cf5e2522 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 7 Sep 2013 23:44:24 -0700 Subject: [PATCH 029/276] Simplified layout API --- src/Layout/forceDirected.js | 110 +++++++++++++++++++++--------------- src/View/renderer.js | 8 +-- 2 files changed, 70 insertions(+), 48 deletions(-) diff --git a/src/Layout/forceDirected.js b/src/Layout/forceDirected.js index 802af88..aa280ae 100644 --- a/src/Layout/forceDirected.js +++ b/src/Layout/forceDirected.js @@ -87,35 +87,41 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { return nodeBodies[nodeId]; }, - releaseBody = function (node) { - nodeBodies[node.id] = null; - delete nodeBodies[node.id]; + releaseBody = function (nodeId) { + nodeBodies[nodeId] = null; + delete nodeBodies[nodeId]; }, springs = {}, - updateBodyMass = function(node) { - var body = getBody(node.id); - body.mass = 1 + graph.getLinks(node.id).length / 3.0; + updateBodyMass = function(nodeId) { + var body = getBody(nodeId); + body.mass = 1 + graph.getLinks(nodeId).length / 3.0; }, - isNodePinned = function(node, body) { - if (!node && !body) { - return true; - } + isNodePinned = function(nodeId) { + var node = graph.getNode(nodeId); - return (node && (node.isPinned || (node.data && node.data.isPinned))) || - (body && body.isPinned); + return (node && (node.isPinned || (node.data && node.data.isPinned))); }, - initNode = function(node) { - var body = getBody(node.id); + isBodyPinned = function (body) { + return body.isPinned; + }, + + initNode = function(nodeId) { + var body = getBody(nodeId); if (!body) { + var node = graph.getNode(nodeId); + if (!node) { + return; // what are you doing? + } + body = new Viva.Graph.Physics.Body(); - nodeBodies[node.id] = body; + nodeBodies[nodeId] = body; var position = getBestNodePosition(node); body.loc(position); - updateBodyMass(node); + updateBodyMass(nodeId); if (isNodePinned(node)) { body.isPinned = true; @@ -124,21 +130,22 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { } }, + initNodeObject = function (node) { + initNode(node.id); + }, + releaseNode = function(node) { var body = getBody(node.id); if (body) { - releaseBody(node); + releaseBody(node.id); forceSimulator.removeBody(body); } }, initLink = function(link) { - var from = graph.getNode(link.fromId), - to = graph.getNode(link.toId); - - updateBodyMass(from); - updateBodyMass(to); + updateBodyMass(link.fromId); + updateBodyMass(link.toId); var fromBody = getBody(link.fromId), toBody = getBody(link.toId), @@ -154,10 +161,10 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { var from = graph.getNode(link.fromId), to = graph.getNode(link.toId); if (from) { - updateBodyMass(from); + updateBodyMass(from.id); } if (to) { - updateBodyMass(to); + updateBodyMass(to.id); } delete springs[link.id]; @@ -170,7 +177,7 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { var change = changes[i]; if (change.changeType === 'add') { if (change.node) { - initNode(change.node); + initNode(change.node.id); } if (change.link) { initLink(change.link); @@ -187,12 +194,11 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { }, initSimulator = function() { - graph.forEachNode(initNode); + graph.forEachNode(initNodeObject); graph.forEachLink(initLink); graph.addEventListener('changed', onGraphChanged); }, - updateNodePositions = function() { var x1 = Number.MAX_VALUE, y1 = Number.MAX_VALUE, @@ -206,7 +212,7 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { if (nodeBodies.hasOwnProperty(key)) { // how about pinned nodes? var body = nodeBodies[key]; - if (isNodePinned(null, body)) { + if (isBodyPinned(body)) { body.location.x = body.prevLocation.x; body.location.y = body.prevLocation.y; } else { @@ -255,6 +261,9 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { } }, + /** + * Performs one step of iterative layout algorithm + */ step: function() { var energy = forceSimulator.run(20); updateNodePositions(); @@ -262,42 +271,55 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { return energy < STABLE_THRESHOLD; }, + /* + * Checks whether given node is pinned; + */ isNodePinned: function (node) { var body = getBody(node.id); - return isNodePinned(node, body); + if (body) { + return isBodyPinned(body); + } }, + /* + * Requests layout algorithm to pin/unpin node to its current position + * Pinned nodes should not be affected by layout algorithm and always + * remain at their position + */ pinNode: function (node, isPinned) { var body = getBody(node.id); body.isPinned = !!isPinned; }, + /* + * Gets position of a node by its id. If node was not seen by this + * layout algorithm undefined value is returned; + */ getNodePosition: function (nodeId) { var body = getBody(nodeId); - return body && body.location; - }, - - getBoundNodePosition: function (node) { - var body = getBody(node.id); if (!body) { - initNode(node); - body = getBody(node.id); + initNode(nodeId); + body = getBody(nodeId); } - return body.location; + return body && body.location; }, - getBoundLinkPosition: function (link) { - var fromNode = graph.getNode(link.fromId), - toNode = graph.getNode(link.toId), - boundFrom = this.getBoundNodePosition(fromNode), - boundTo = this.getBoundNodePosition(toNode); + /** + * Returns {from, to} position of a link. + */ + getLinkPosition: function (link) { + var from = this.getNodePosition(link.fromId), + to = this.getNodePosition(link.toId); return { - from : boundFrom, - to : boundTo + from : from, + to : to }; }, + /** + * Sets position of a node to a given coordinates + */ setNodePosition: function (node, x, y) { var body = getBody(node.id); if (body) { diff --git a/src/View/renderer.js b/src/View/renderer.js index 184caea..d380098 100644 --- a/src/View/renderer.js +++ b/src/View/renderer.js @@ -154,8 +154,8 @@ Viva.Graph.View.renderer = function (graph, settings) { }, createNodeUi = function (node) { - var boundPosition = layout.getBoundNodePosition(node); - graphics.addNode(node, boundPosition); + var nodePosition = layout.getNodePosition(node.id); + graphics.addNode(node, nodePosition); }, removeNodeUi = function (node) { @@ -163,8 +163,8 @@ Viva.Graph.View.renderer = function (graph, settings) { }, createLinkUi = function (link) { - var boundLinkPosition = layout.getBoundLinkPosition(link); - graphics.addLink(link, boundLinkPosition); + var linkPosition = layout.getLinkPosition(link); + graphics.addLink(link, linkPosition); }, removeLinkUi = function (link) { From 76e84b87c47ab7b072d8eca15abd17bed8b6f113 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 7 Sep 2013 23:45:04 -0700 Subject: [PATCH 030/276] Updated constant layout to match recent changes --- src/Layout/constant.js | 71 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 63 insertions(+), 8 deletions(-) diff --git a/src/Layout/constant.js b/src/Layout/constant.js index f64b144..6d22a6a 100644 --- a/src/Layout/constant.js +++ b/src/Layout/constant.js @@ -23,18 +23,21 @@ Viva.Graph.Layout.constant = function (graph, userSettings) { return new Viva.Graph.Point2d(rand.next(userSettings.maxX), rand.next(userSettings.maxY)); }, - updateGraphRect = function (node, graphRect) { - if (node.position.x < graphRect.x1) { graphRect.x1 = node.position.x; } - if (node.position.x > graphRect.x2) { graphRect.x2 = node.position.x; } - if (node.position.y < graphRect.y1) { graphRect.y1 = node.position.y; } - if (node.position.y > graphRect.y2) { graphRect.y2 = node.position.y; } + updateGraphRect = function (position, graphRect) { + if (position.x < graphRect.x1) { graphRect.x1 = position.x; } + if (position.x > graphRect.x2) { graphRect.x2 = position.x; } + if (position.y < graphRect.y1) { graphRect.y1 = position.y; } + if (position.y > graphRect.y2) { graphRect.y2 = position.y; } }, + layoutNodes = {}, + ensureNodeInitialized = function (node) { - if (!node.hasOwnProperty('position')) { - node.position = placeNodeCallback(node); + if (!node) { return; } + if (!layoutNodes[node.id]) { + layoutNodes[node.id] = placeNodeCallback(node); } - updateGraphRect(node, graphRect); + updateGraphRect(layoutNodes[node.id], graphRect); }, updateNodePositions = function () { @@ -97,6 +100,58 @@ Viva.Graph.Layout.constant = function (graph, userSettings) { graph.removeEventListener('change', onGraphChanged); }, + /* + * Checks whether given node is pinned; all nodes in this layout are pinned. + */ + isNodePinned: function (node) { + return true; + }, + + /* + * Requests layout algorithm to pin/unpin node to its current position + * Pinned nodes should not be affected by layout algorithm and always + * remain at their position + */ + pinNode: function (node, isPinned) { + // noop + }, + + /* + * Gets position of a node by its id. If node was not seen by this + * layout algorithm undefined value is returned; + */ + getNodePosition: function (nodeId) { + var pos = layoutNodes[nodeId]; + if (!pos) { + ensureNodeInitialized(graph.getNode(nodeId)); + } + return pos; + }, + + /** + * Returns {from, to} position of a link. + */ + getLinkPosition: function (link) { + var from = this.getNodePosition(link.fromId), + to = this.getNodePosition(link.toId); + + return { + from : from, + to : to + }; + }, + + /** + * Sets position of a node to a given coordinates + */ + setNodePosition: function (node, x, y) { + var pos = layoutNodes[node.id]; + if (pos) { + pos.x = x; + pos.y = y; + } + }, + // Layout specific methods: /** From 10227e95d6843d378e8072c14080533525437120 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 7 Sep 2013 23:47:31 -0700 Subject: [PATCH 031/276] Updated constan layout tests --- dist/vivagraph.js | 189 +++++++++++++++++++++--------- dist/vivagraph.min.js | 4 +- unit_tests/test_constantLayout.js | 17 +-- 3 files changed, 145 insertions(+), 65 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index b12289a..43794a6 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -2271,35 +2271,41 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { return nodeBodies[nodeId]; }, - releaseBody = function (node) { - nodeBodies[node.id] = null; - delete nodeBodies[node.id]; + releaseBody = function (nodeId) { + nodeBodies[nodeId] = null; + delete nodeBodies[nodeId]; }, springs = {}, - updateBodyMass = function(node) { - var body = getBody(node.id); - body.mass = 1 + graph.getLinks(node.id).length / 3.0; + updateBodyMass = function(nodeId) { + var body = getBody(nodeId); + body.mass = 1 + graph.getLinks(nodeId).length / 3.0; }, - isNodePinned = function(node, body) { - if (!node && !body) { - return true; - } + isNodePinned = function(nodeId) { + var node = graph.getNode(nodeId); - return (node && (node.isPinned || (node.data && node.data.isPinned))) || - (body && body.isPinned); + return (node && (node.isPinned || (node.data && node.data.isPinned))); }, - initNode = function(node) { - var body = getBody(node.id); + isBodyPinned = function (body) { + return body.isPinned; + }, + + initNode = function(nodeId) { + var body = getBody(nodeId); if (!body) { + var node = graph.getNode(nodeId); + if (!node) { + return; // what are you doing? + } + body = new Viva.Graph.Physics.Body(); - nodeBodies[node.id] = body; + nodeBodies[nodeId] = body; var position = getBestNodePosition(node); body.loc(position); - updateBodyMass(node); + updateBodyMass(nodeId); if (isNodePinned(node)) { body.isPinned = true; @@ -2308,21 +2314,22 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { } }, + initNodeObject = function (node) { + initNode(node.id); + }, + releaseNode = function(node) { var body = getBody(node.id); if (body) { - releaseBody(node); + releaseBody(node.id); forceSimulator.removeBody(body); } }, initLink = function(link) { - var from = graph.getNode(link.fromId), - to = graph.getNode(link.toId); - - updateBodyMass(from); - updateBodyMass(to); + updateBodyMass(link.fromId); + updateBodyMass(link.toId); var fromBody = getBody(link.fromId), toBody = getBody(link.toId), @@ -2338,10 +2345,10 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { var from = graph.getNode(link.fromId), to = graph.getNode(link.toId); if (from) { - updateBodyMass(from); + updateBodyMass(from.id); } if (to) { - updateBodyMass(to); + updateBodyMass(to.id); } delete springs[link.id]; @@ -2354,7 +2361,7 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { var change = changes[i]; if (change.changeType === 'add') { if (change.node) { - initNode(change.node); + initNode(change.node.id); } if (change.link) { initLink(change.link); @@ -2371,12 +2378,11 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { }, initSimulator = function() { - graph.forEachNode(initNode); + graph.forEachNode(initNodeObject); graph.forEachLink(initLink); graph.addEventListener('changed', onGraphChanged); }, - updateNodePositions = function() { var x1 = Number.MAX_VALUE, y1 = Number.MAX_VALUE, @@ -2390,7 +2396,7 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { if (nodeBodies.hasOwnProperty(key)) { // how about pinned nodes? var body = nodeBodies[key]; - if (isNodePinned(null, body)) { + if (isBodyPinned(body)) { body.location.x = body.prevLocation.x; body.location.y = body.prevLocation.y; } else { @@ -2439,6 +2445,9 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { } }, + /** + * Performs one step of iterative layout algorithm + */ step: function() { var energy = forceSimulator.run(20); updateNodePositions(); @@ -2446,42 +2455,55 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { return energy < STABLE_THRESHOLD; }, + /* + * Checks whether given node is pinned; + */ isNodePinned: function (node) { var body = getBody(node.id); - return isNodePinned(node, body); + if (body) { + return isBodyPinned(body); + } }, + /* + * Requests layout algorithm to pin/unpin node to its current position + * Pinned nodes should not be affected by layout algorithm and always + * remain at their position + */ pinNode: function (node, isPinned) { var body = getBody(node.id); body.isPinned = !!isPinned; }, + /* + * Gets position of a node by its id. If node was not seen by this + * layout algorithm undefined value is returned; + */ getNodePosition: function (nodeId) { var body = getBody(nodeId); - return body && body.location; - }, - - getBoundNodePosition: function (node) { - var body = getBody(node.id); if (!body) { - initNode(node); - body = getBody(node.id); + initNode(nodeId); + body = getBody(nodeId); } - return body.location; + return body && body.location; }, - getBoundLinkPosition: function (link) { - var fromNode = graph.getNode(link.fromId), - toNode = graph.getNode(link.toId), - boundFrom = this.getBoundNodePosition(fromNode), - boundTo = this.getBoundNodePosition(toNode); + /** + * Returns {from, to} position of a link. + */ + getLinkPosition: function (link) { + var from = this.getNodePosition(link.fromId), + to = this.getNodePosition(link.toId); return { - from : boundFrom, - to : boundTo + from : from, + to : to }; }, + /** + * Sets position of a node to a given coordinates + */ setNodePosition: function (node, x, y) { var body = getBody(node.id); if (body) { @@ -2617,18 +2639,21 @@ Viva.Graph.Layout.constant = function (graph, userSettings) { return new Viva.Graph.Point2d(rand.next(userSettings.maxX), rand.next(userSettings.maxY)); }, - updateGraphRect = function (node, graphRect) { - if (node.position.x < graphRect.x1) { graphRect.x1 = node.position.x; } - if (node.position.x > graphRect.x2) { graphRect.x2 = node.position.x; } - if (node.position.y < graphRect.y1) { graphRect.y1 = node.position.y; } - if (node.position.y > graphRect.y2) { graphRect.y2 = node.position.y; } + updateGraphRect = function (position, graphRect) { + if (position.x < graphRect.x1) { graphRect.x1 = position.x; } + if (position.x > graphRect.x2) { graphRect.x2 = position.x; } + if (position.y < graphRect.y1) { graphRect.y1 = position.y; } + if (position.y > graphRect.y2) { graphRect.y2 = position.y; } }, + layoutNodes = {}, + ensureNodeInitialized = function (node) { - if (!node.hasOwnProperty('position')) { - node.position = placeNodeCallback(node); + if (!node) { return; } + if (!layoutNodes[node.id]) { + layoutNodes[node.id] = placeNodeCallback(node); } - updateGraphRect(node, graphRect); + updateGraphRect(layoutNodes[node.id], graphRect); }, updateNodePositions = function () { @@ -2691,6 +2716,58 @@ Viva.Graph.Layout.constant = function (graph, userSettings) { graph.removeEventListener('change', onGraphChanged); }, + /* + * Checks whether given node is pinned; all nodes in this layout are pinned. + */ + isNodePinned: function (node) { + return true; + }, + + /* + * Requests layout algorithm to pin/unpin node to its current position + * Pinned nodes should not be affected by layout algorithm and always + * remain at their position + */ + pinNode: function (node, isPinned) { + // noop + }, + + /* + * Gets position of a node by its id. If node was not seen by this + * layout algorithm undefined value is returned; + */ + getNodePosition: function (nodeId) { + var pos = layoutNodes[nodeId]; + if (!pos) { + ensureNodeInitialized(graph.getNode(nodeId)); + } + return pos; + }, + + /** + * Returns {from, to} position of a link. + */ + getLinkPosition: function (link) { + var from = this.getNodePosition(link.fromId), + to = this.getNodePosition(link.toId); + + return { + from : from, + to : to + }; + }, + + /** + * Sets position of a node to a given coordinates + */ + setNodePosition: function (node, x, y) { + var pos = layoutNodes[node.id]; + if (pos) { + pos.x = x; + pos.y = y; + } + }, + // Layout specific methods: /** @@ -2876,8 +2953,8 @@ Viva.Graph.View.renderer = function (graph, settings) { }, createNodeUi = function (node) { - var boundPosition = layout.getBoundNodePosition(node); - graphics.addNode(node, boundPosition); + var nodePosition = layout.getNodePosition(node.id); + graphics.addNode(node, nodePosition); }, removeNodeUi = function (node) { @@ -2885,8 +2962,8 @@ Viva.Graph.View.renderer = function (graph, settings) { }, createLinkUi = function (link) { - var boundLinkPosition = layout.getBoundLinkPosition(link); - graphics.addLink(link, boundLinkPosition); + var linkPosition = layout.getLinkPosition(link); + graphics.addLink(link, linkPosition); }, removeLinkUi = function (link) { diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 470ef6b..0bfb3ff 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.0",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){function e(){var e=4022871197,t=function(t){var n;for(t=""+t,n=0;t.length>n;n++){e+=t.charCodeAt(n);var r=.02519603282416938*e;e=r>>>0,r-=e,r*=e,e=r>>>0,r-=e,e+=4294967296*r}return 2.3283064365386963e-10*(e>>>0)};return t.version="Mash 0.9",t}function t(t){return function(t){var n,r,i=0,o=58,a=119,u=178,s=[],f=e();for(0===t.length&&(t=[+new Date]),n=0;256>n;n++)s[n]=f(" "),s[n]-=4.76837158203125e-7*f(" "),0>s[n]&&(s[n]+=1);for(r=0;t.length>r;r++)for(n=0;256>n;n++)s[n]-=f(t[r]),s[n]-=4.76837158203125e-7*f(t[r]),0>s[n]&&(s[n]+=1);f=null;var c=function(){var e;return i=255&i+1,o=255&o+1,a=255&a+1,u=255&u+1,e=s[i]-s[o],0>e&&(e+=1),e-=s[a],0>e&&(e+=1),e-=s[u],0>e&&(e+=1),s[i]=e,e};return c.uint32=function(){return 4294967296*c()>>>0},c.fract53=c,c.version="LFIB4 0.9",c.args=t,c}(t)}var n=new t(Array.prototype.slice.call(arguments));return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,l=0,d=0,h=!1,p=0,v=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-l,y:r-d}),l=t,d=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(l=e.clientX,d=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:l,y:d}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},P=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=v(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},E=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",P,!1):e.addEventListener("DOMMouseScroll",P,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",P,!1):e.removeEventListener("DOMMouseScroll",P,!1)),i=t},N=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=N(e.touches[0],e.touches[1]),r=0;p>n?r=-1:n>p&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),p=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),l=n.clientX,d=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:l,y:d}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),p=N(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return E(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),E(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,l,d,h,p,v,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,d=n*t-e*r,m=s*i+c*o+d,g=s*a+c*u+d,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,l=i-a,h=a*o-i*u,p=f*e+l*t+h,v=f*n+l*r+h,0!==p&&0!==v&&p>=0==v>=0?null:(y=s*l-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-l*d,V.x=(0>w?w-x:w+x)/y,w=f*d-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var l=i(a);l===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=l}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},l=function(e){return e&&"object"==typeof e&&"number"==typeof e.length&&"function"==typeof e.splice&&!e.propertyIsEnumerable("length")},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);if(i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),n){var o,a=i.data||{},c=typeof n;if("string"===c||l(n)||"number"===c||"boolean"===c)a=n;else if("undefined"===c)a=null;else for(o in n)n.hasOwnProperty(o)&&(a[o]=n[o]);i.data=a}return e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),l=n.hasOwnProperty(f);(l||this.hasLink(e,r))&&(l||(n[f]=0),f+="@"+ ++n[f]);var d=new Viva.Graph.Link(e,r,i,f);return t.push(d),o.links.push(d),a.links.push(d),c(d,"add"),s(this),d},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,l=Math.sqrt(f*f+c*c);l>r&&(u.velocity.x=r*f/l,u.velocity.y=r*c/l),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,l=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},d=l(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},p=function(e){for(o.reset(),o.push(d,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,p=n.top,v=(n.bottom+p)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>v){s+=2;var g=p;p=v,v+=v-g}var y=n.quads[s];y||(y=l(),y.left=f,y.top=p,y.right=c,y.bottom=v,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},v=function(e){var t,n,o,s,f=i,c=1,l=0,h=1;for(f[0]=d;c;){var p=f[l],v=p.body;c-=1,l+=1,v&&v!==e?(n=v.location.x-e.location.x,o=v.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=p.massX/p.mass-e.location.x,o=p.massY/p.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(p.right-p.left)/s?(t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(p.quads[0]&&(f[h]=p.quads[0],c+=1,h+=1),p.quads[1]&&(f[h]=p.quads[1],c+=1,h+=1),p.quads[2]&&(f[h]=p.quads[2],c+=1,h+=1),p.quads[3]&&(f[h]=p.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,v=o-r;for(h>v?o=r+h:i=n+v,c=0,d=l(),d.left=n,d.right=i,d.top=r,d.bottom=o,t=u;t--;)p(a[t],d)};return{insert:p,init:m,update:v,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};i="number"==typeof i?i:1;var o=new Viva.Graph.Physics.Spring(e,t,n,r>=0?r:-1,i);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),f={},c=function(e){var n=(u.x1+u.x2)/2,r=(u.y1+u.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],a=o.fromId!==e.id?f[o.fromId]:f[o.toId];a&&a.location&&(n=a.location.x,r=a.location.y)}return{x:n+s.next(i)-i/2,y:r+s.next(i)-i/2}},l=function(e){return f[e]},d=function(e){f[e.id]=null,delete f[e.id]},h={},p=function(t){var n=l(t.id);n.mass=1+e.getLinks(t.id).length/3},v=function(e,t){return e||t?e&&(e.isPinned||e.data&&e.data.isPinned)||t&&t.isPinned:!0},m=function(e){var t=l(e.id);if(!t){t=new Viva.Graph.Physics.Body,f[e.id]=t;var n=c(e);t.loc(n),p(e),v(e)&&(t.isPinned=!0),r.addBody(t)}},g=function(e){var t=l(e.id);t&&(d(e),r.removeBody(t))},y=function(t){var n=e.getNode(t.fromId),i=e.getNode(t.toId);p(n),p(i);var o=l(t.fromId),a=l(t.toId),u=r.addSpring(o,a,-1,t.weight);h[t.id]=u},x=function(t){var n=h[t.id];if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&p(i),o&&p(o),delete h[t.id],r.removeSpring(n)}},w=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&m(n.node),n.link&&y(n.link)):"remove"===n.changeType&&(n.node&&g(n.node),n.link&&x(n.link))}},V=function(){e.forEachNode(m),e.forEachLink(y),e.addEventListener("changed",w)},b=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in f)if(f.hasOwnProperty(o)){var a=f[o];v(null,a)?(a.location.x=a.prevLocation.x,a.location.y=a.prevLocation.y):(a.prevLocation.x=a.location.x,a.prevLocation.y=a.location.y),t>a.location.x&&(t=a.location.x),a.location.x>r&&(r=a.location.x),n>a.location.y&&(n=a.location.y),a.location.y>i&&(i=a.location.y)}u.x1=t,u.x2=r,u.y1=n,u.y2=i}};return r.setSpringForce(o),r.setNbodyForce(i),r.setDragForce(a),V(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(20);return b(),n>e},isNodePinned:function(e){var t=l(e.id);return v(e,t)},pinNode:function(e,t){var n=l(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=l(e);return t&&t.location},getBoundNodePosition:function(e){var t=l(e.id);return t||(m(e),t=l(e.id)),t.location},getBoundLinkPosition:function(t){var n=e.getNode(t.fromId),r=e.getNode(t.toId),i=this.getBoundNodePosition(n),o=this.getBoundNodePosition(r);return{from:i,to:o}},setNodePosition:function(e,t,n){var r=l(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",w)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.position.xt.x2&&(t.x2=e.position.x),e.position.yt.y2&&(t.y2=e.position.y)},a=function(e){e.hasOwnProperty("position")||(e.position=i(e)),o(e,r)},u=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(a))},s=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&a(n.node)}};return{run:function(){this.step()},step:function(){return u(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",s)},placeNode:function(e){return"function"==typeof e?(i=e,u(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,l=!0,d=0,h=0,p=!1,v=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return p=u.step()&&!v,V(),!p},P=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(d=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},E=function(){p=!1,i.restart()},N=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),l=!1},L=function(e){var t=u.getBoundNodePosition(e);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getBoundLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),v=!0,E()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),v=!0,V()},onStop:function(){u.pinNode(e,t),v=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),l&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(l=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},R=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);E()},D=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",R),o=null)},z=function(){x.on("resize",D),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){var r=Math.pow(1.4,0>t?-.2:.2);g.scale=s.scale(r,n),V(),w.fire("scale",g.scale)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",R)},B=function(){c=!1,O(),F(),x.stop("resize",D),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),N(),G(),C(),z(),c=!0),P(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},dispose:function(){B()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],l=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,l,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t); -return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},l=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},d=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?l(e):(l=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,d()},translateRel:function(e,r){t+=e,n+=r,d()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,d()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),l=f.attr("id"),d=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&l===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&d===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i,o=1,a={},u={},s=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},f=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},c=function(){return Viva.Graph.svg("line").attr("stroke","#999")},l=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},d=function(e){e.fire("rescaled")},h={x:0,y:0},p={x:0,y:0},v={x:0,y:0},m=function(){if(e){var t="matrix("+o+", 0, 0,"+o+","+n+","+r+")";e.attr("transform",t)}},g={getNodeUI:function(e){return a[e]},getLinkUI:function(e){return u[e]},node:function(e){return"function"==typeof e?(s=e,this):void 0},link:function(e){return"function"==typeof e?(c=e,this):void 0},placeNode:function(e){return f=e,this},placeLink:function(e){return l=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,m()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(i,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(i).translate(-u.x,-u.y),f=e.getCTM().multiply(s);o=f.a,n=f.e,r=f.f;var c="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",c),d(this),o},resetScale:function(){o=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),d(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),m(),"function"==typeof i&&i(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(t,n){var r=c(t);if(r)return r.position=n,r.link=t,u[t.id]=r,e.childElementCount>0?e.insertBefore(r,e.firstChild):e.appendChild(r),r},releaseLink:function(t){var n=u[t.id];n&&(e.removeChild(n),delete u[t.id])},addNode:function(t,n){var r=s(t);if(r)return r.position=n,r.node=t,a[t.id]=r,e.appendChild(r),r},releaseNode:function(t){var n=a[t.id];n&&(e.removeChild(n),delete a[t.id])},renderNodes:function(){for(var e in a)if(a.hasOwnProperty(e)){var t=a[e];h.x=t.position.x,h.y=t.position.y,f(t,h,t.node)}},renderLinks:function(){for(var e in u)if(u.hasOwnProperty(e)){var t=u[e];p.x=t.position.from.x,p.y=t.position.from.y,v.x=t.position.to.x,v.y=t.position.to.y,l(t,p,v,t.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):i=e),t},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(g).extend(),g},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,l=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(l.x)+" "+Math.round(l.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),d=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),p=new Float32Array(h),v=new Uint32Array(h),m=0,g=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(v),p=t,v=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(d,l),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;p[n*f]=t.x,p[n*f+1]=t.y,p[n*f+2]=e.size,v[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(v,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),p=0,v=new ArrayBuffer(16*l),m=new Float32Array(v),g=new Uint32Array(v),y=function(){if((p+1)*l>v.byteLength){var e=new ArrayBuffer(2*v.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,v=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,d),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),p+=1,o=e.id},removeLink:function(e){p>0&&(p-=1),p>e.id&&p>0&&r.copyArrayPart(g,e.id*c,p*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,v,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*p),o=p-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},l=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},d=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},p=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},v=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=d(e),o={offset:e};r.textureNumber>=s.length&&l();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=d(t.offset),r=d(o);v(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],p(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){p(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,l=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),d=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,p=0,v=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(d,l),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;v[n]=t.x-e.size,v[n+1]=t.y-e.size,v[n+2]=4*e._offset,v[n+3]=t.x+e.size,v[n+4]=t.y-e.size,v[n+5]=4*e._offset+1,v[n+6]=t.x-e.size,v[n+7]=t.y+e.size,v[n+8]=4*e._offset+2,v[n+9]=t.x-e.size,v[n+10]=t.y+e.size,v[n+11]=4*e._offset+2,v[n+12]=t.x+e.size,v[n+13]=t.y-e.size,v[n+14]=4*e._offset+1,v[n+15]=t.x+e.size,v[n+16]=t.y+e.size,v[n+17]=4*e._offset+3},createNode:function(t){v=i.extendArray(v,p,c),p+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){p>0&&(p-=1),p>t.id&&p>0&&(t.src&&e.remove(t.src),i.copyArrayPart(v,t.id*c,p*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,v,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*p)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f,c=0,l=0,d=[],h=[],p={},v={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(a),g.updateTransform(a)},V=function(){a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},P=function(e){e.fire("rescaled")},E={getLinkUI:function(e){return v[e]},getNodeUI:function(e){return p[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return u=e,this},placeLink:function(e){return s=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){l>0&&m.render(),c>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(){b()},addLink:function(e,t){var n=l++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,v[e.id]=r,r},addNode:function(e,t){var n=c++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),d[n]=r,p[e.id]=r,r},translateRel:function(e,t){a[12]+=2*a[0]*e/i/a[0],a[13]-=2*a[5]*t/o/a[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=a[12],r-=a[13],a[12]+=n*(1-e),a[13]+=r*(1-e),a[0]*=e,a[5]*=e,w(),P(this),a[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var s="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(s),s}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof f&&f(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){l>0&&(l-=1);var t=v[e.id];delete v[e.id],m.removeLink(t);var n=t.id;if(l>n){if(0===l||l===n)return;var r=h[l];h[n]=r,r.id=n}},releaseNode:function(e){c>0&&(c-=1);var t=p[e.id];delete p[e.id],g.removeNode(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=d[c];d[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;c>t;++t){var n=d[t];e.x=n.position.x,e.y=-n.position.y,u&&u(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;l>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,s&&s(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):f=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-a[12])/a[0],e.y=(e.y-a[13])/a[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;c>n;++n)if(t(d[n],e.x,e.y))return d[n].node;return null}};return Viva.Graph.Utils.events(E).extend(),E},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},i=function(t){return e.getNodeAtClientPos(t,r)},o=null,a=[],u=[],s=[],f=[],c=[],l=[],d=[],h=Viva.Graph.Utils.events(window.document),p=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},v=function(e){return p(e),!1},m=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(e){var r={x:0,y:0},g=null,y=+new Date,x=function(e){m(c,[g,e]),r.x=e.clientX,r.y=e.clientY},w=function(){h.stop("mousemove",x),h.stop("mouseup",w)},V=function(){n=e.getBoundingClientRect()};window.addEventListener("resize",V),V(),e.addEventListener("mousemove",function(e){if(!o){var t,s=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,t=i(r),t&&g!==t?(g=t,s=s||m(a,[g])):null===t&&g!==t&&(s=s||m(u,[g]),g=null),s&&p(e)}}),e.addEventListener("mousedown",function(e){var o,a=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]?(a=m(s,o),h.on("mousemove",x),h.on("mouseup",w),t=window.document.onselectstart,window.document.onselectstart=v,g=o[0]):g=null,a&&p(e)}),e.addEventListener("mouseup",function(e){var o,a=+new Date;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]&&(window.document.onselectstart=t,400>a-y&&o[0]===g?m(d,o):m(l,o),y=a,m(f,o)&&p(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&l.push(e),this},dblClick:function(e){return"function"==typeof e&&d.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file +var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.0",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){function e(){var e=4022871197,t=function(t){var n;for(t=""+t,n=0;t.length>n;n++){e+=t.charCodeAt(n);var r=.02519603282416938*e;e=r>>>0,r-=e,r*=e,e=r>>>0,r-=e,e+=4294967296*r}return 2.3283064365386963e-10*(e>>>0)};return t.version="Mash 0.9",t}function t(t){return function(t){var n,r,i=0,o=58,a=119,u=178,s=[],f=e();for(0===t.length&&(t=[+new Date]),n=0;256>n;n++)s[n]=f(" "),s[n]-=4.76837158203125e-7*f(" "),0>s[n]&&(s[n]+=1);for(r=0;t.length>r;r++)for(n=0;256>n;n++)s[n]-=f(t[r]),s[n]-=4.76837158203125e-7*f(t[r]),0>s[n]&&(s[n]+=1);f=null;var c=function(){var e;return i=255&i+1,o=255&o+1,a=255&a+1,u=255&u+1,e=s[i]-s[o],0>e&&(e+=1),e-=s[a],0>e&&(e+=1),e-=s[u],0>e&&(e+=1),s[i]=e,e};return c.uint32=function(){return 4294967296*c()>>>0},c.fract53=c,c.version="LFIB4 0.9",c.args=t,c}(t)}var n=new t(Array.prototype.slice.call(arguments));return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,l=0,d=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-l,y:r-d}),l=t,d=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(l=e.clientX,d=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:l,y:d}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},P=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},N=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",P,!1):e.addEventListener("DOMMouseScroll",P,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",P,!1):e.removeEventListener("DOMMouseScroll",P,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),l=n.clientX,d=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:l,y:d}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),N(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,l,d,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,d=n*t-e*r,m=s*i+c*o+d,g=s*a+c*u+d,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,l=i-a,h=a*o-i*u,v=f*e+l*t+h,p=f*n+l*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*l-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-l*d,V.x=(0>w?w-x:w+x)/y,w=f*d-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var l=i(a);l===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=l}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},l=function(e){return e&&"object"==typeof e&&"number"==typeof e.length&&"function"==typeof e.splice&&!e.propertyIsEnumerable("length")},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);if(i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),n){var o,a=i.data||{},c=typeof n;if("string"===c||l(n)||"number"===c||"boolean"===c)a=n;else if("undefined"===c)a=null;else for(o in n)n.hasOwnProperty(o)&&(a[o]=n[o]);i.data=a}return e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),l=n.hasOwnProperty(f);(l||this.hasLink(e,r))&&(l||(n[f]=0),f+="@"+ ++n[f]);var d=new Viva.Graph.Link(e,r,i,f);return t.push(d),o.links.push(d),a.links.push(d),c(d,"add"),s(this),d},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,l=Math.sqrt(f*f+c*c);l>r&&(u.velocity.x=r*f/l,u.velocity.y=r*c/l),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,l=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},d=l(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(d,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=l(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,l=0,h=1;for(f[0]=d;c;){var v=f[l],p=v.body;c-=1,l+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,d=l(),d.left=n,d.right=i,d.top=r,d.bottom=o,t=u;t--;)v(a[t],d)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};i="number"==typeof i?i:1;var o=new Viva.Graph.Physics.Spring(e,t,n,r>=0?r:-1,i);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),f={},c=function(e){var n=(u.x1+u.x2)/2,r=(u.y1+u.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],a=o.fromId!==e.id?f[o.fromId]:f[o.toId];a&&a.location&&(n=a.location.x,r=a.location.y)}return{x:n+s.next(i)-i/2,y:r+s.next(i)-i/2}},l=function(e){return f[e]},d=function(e){f[e]=null,delete f[e]},h={},v=function(t){var n=l(t);n.mass=1+e.getLinks(t).length/3},p=function(t){var n=e.getNode(t);return n&&(n.isPinned||n.data&&n.data.isPinned)},m=function(e){return e.isPinned},g=function(t){var n=l(t);if(!n){var i=e.getNode(t);if(!i)return;n=new Viva.Graph.Physics.Body,f[t]=n;var o=c(i);n.loc(o),v(t),p(i)&&(n.isPinned=!0),r.addBody(n)}},y=function(e){g(e.id)},x=function(e){var t=l(e.id);t&&(d(e.id),r.removeBody(t))},w=function(e){v(e.fromId),v(e.toId);var t=l(e.fromId),n=l(e.toId),i=r.addSpring(t,n,-1,e.weight);h[e.id]=i},V=function(t){var n=h[t.id];if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&v(i.id),o&&v(o.id),delete h[t.id],r.removeSpring(n)}},b=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&g(n.node.id),n.link&&w(n.link)):"remove"===n.changeType&&(n.node&&x(n.node),n.link&&V(n.link))}},P=function(){e.forEachNode(y),e.forEachLink(w),e.addEventListener("changed",b)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in f)if(f.hasOwnProperty(o)){var a=f[o];m(a)?(a.location.x=a.prevLocation.x,a.location.y=a.prevLocation.y):(a.prevLocation.x=a.location.x,a.prevLocation.y=a.location.y),t>a.location.x&&(t=a.location.x),a.location.x>r&&(r=a.location.x),n>a.location.y&&(n=a.location.y),a.location.y>i&&(i=a.location.y)}u.x1=t,u.x2=r,u.y1=n,u.y2=i}};return r.setSpringForce(o),r.setNbodyForce(i),r.setDragForce(a),P(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(20);return N(),n>e},isNodePinned:function(e){var t=l(e.id);return t?m(t):void 0},pinNode:function(e,t){var n=l(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=l(e);return t||(g(e),t=l(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=l(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",b)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a={},u=function(e){e&&(a[e.id]||(a[e.id]=i(e)),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&u(n.node)}};return{run:function(){this.step()},step:function(){return s(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,l=!0,d=0,h=0,v=!1,p=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return v=u.step()&&!p,V(),!v},P=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(d=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},N=function(){v=!1,i.restart()},E=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),l=!1},L=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),p=!0,N()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),p=!0,V()},onStop:function(){u.pinNode(e,t),p=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),l&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(l=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},R=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);N()},D=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",R),o=null)},z=function(){x.on("resize",D),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){var r=Math.pow(1.4,0>t?-.2:.2);g.scale=s.scale(r,n),V(),w.fire("scale",g.scale)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",R)},B=function(){c=!1,O(),F(),x.stop("resize",D),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),E(),G(),C(),z(),c=!0),P(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},dispose:function(){B()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],l=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,l,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"}; +var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},l=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},d=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?l(e):(l=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,d()},translateRel:function(e,r){t+=e,n+=r,d()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,d()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),l=f.attr("id"),d=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&l===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&d===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i,o=1,a={},u={},s=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},f=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},c=function(){return Viva.Graph.svg("line").attr("stroke","#999")},l=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},d=function(e){e.fire("rescaled")},h={x:0,y:0},v={x:0,y:0},p={x:0,y:0},m=function(){if(e){var t="matrix("+o+", 0, 0,"+o+","+n+","+r+")";e.attr("transform",t)}},g={getNodeUI:function(e){return a[e]},getLinkUI:function(e){return u[e]},node:function(e){return"function"==typeof e?(s=e,this):void 0},link:function(e){return"function"==typeof e?(c=e,this):void 0},placeNode:function(e){return f=e,this},placeLink:function(e){return l=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,m()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(i,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(i).translate(-u.x,-u.y),f=e.getCTM().multiply(s);o=f.a,n=f.e,r=f.f;var c="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",c),d(this),o},resetScale:function(){o=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),d(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),m(),"function"==typeof i&&i(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(t,n){var r=c(t);if(r)return r.position=n,r.link=t,u[t.id]=r,e.childElementCount>0?e.insertBefore(r,e.firstChild):e.appendChild(r),r},releaseLink:function(t){var n=u[t.id];n&&(e.removeChild(n),delete u[t.id])},addNode:function(t,n){var r=s(t);if(r)return r.position=n,r.node=t,a[t.id]=r,e.appendChild(r),r},releaseNode:function(t){var n=a[t.id];n&&(e.removeChild(n),delete a[t.id])},renderNodes:function(){for(var e in a)if(a.hasOwnProperty(e)){var t=a[e];h.x=t.position.x,h.y=t.position.y,f(t,h,t.node)}},renderLinks:function(){for(var e in u)if(u.hasOwnProperty(e)){var t=u[e];v.x=t.position.from.x,v.y=t.position.from.y,p.x=t.position.to.x,p.y=t.position.to.y,l(t,v,p,t.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):i=e),t},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(g).extend(),g},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,l=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(l.x)+" "+Math.round(l.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),d=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),v=new Float32Array(h),p=new Uint32Array(h),m=0,g=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(p),v=t,p=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(d,l),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;v[n*f]=t.x,v[n*f+1]=t.y,v[n*f+2]=e.size,p[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(p,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),v=0,p=new ArrayBuffer(16*l),m=new Float32Array(p),g=new Uint32Array(p),y=function(){if((v+1)*l>p.byteLength){var e=new ArrayBuffer(2*p.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,p=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,d),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),v+=1,o=e.id},removeLink:function(e){v>0&&(v-=1),v>e.id&&v>0&&r.copyArrayPart(g,e.id*c,v*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,p,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*v),o=v-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},l=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},d=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},v=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},p=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=d(e),o={offset:e};r.textureNumber>=s.length&&l();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=d(t.offset),r=d(o);p(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],v(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){v(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,l=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),d=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,v=0,p=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(d,l),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;p[n]=t.x-e.size,p[n+1]=t.y-e.size,p[n+2]=4*e._offset,p[n+3]=t.x+e.size,p[n+4]=t.y-e.size,p[n+5]=4*e._offset+1,p[n+6]=t.x-e.size,p[n+7]=t.y+e.size,p[n+8]=4*e._offset+2,p[n+9]=t.x-e.size,p[n+10]=t.y+e.size,p[n+11]=4*e._offset+2,p[n+12]=t.x+e.size,p[n+13]=t.y-e.size,p[n+14]=4*e._offset+1,p[n+15]=t.x+e.size,p[n+16]=t.y+e.size,p[n+17]=4*e._offset+3},createNode:function(t){p=i.extendArray(p,v,c),v+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){v>0&&(v-=1),v>t.id&&v>0&&(t.src&&e.remove(t.src),i.copyArrayPart(p,t.id*c,v*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,p,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*v)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f,c=0,l=0,d=[],h=[],v={},p={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(a),g.updateTransform(a)},V=function(){a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},P=function(e){e.fire("rescaled")},N={getLinkUI:function(e){return p[e]},getNodeUI:function(e){return v[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return u=e,this},placeLink:function(e){return s=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){l>0&&m.render(),c>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(){b()},addLink:function(e,t){var n=l++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,p[e.id]=r,r},addNode:function(e,t){var n=c++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),d[n]=r,v[e.id]=r,r},translateRel:function(e,t){a[12]+=2*a[0]*e/i/a[0],a[13]-=2*a[5]*t/o/a[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=a[12],r-=a[13],a[12]+=n*(1-e),a[13]+=r*(1-e),a[0]*=e,a[5]*=e,w(),P(this),a[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var s="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(s),s}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof f&&f(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){l>0&&(l-=1);var t=p[e.id];delete p[e.id],m.removeLink(t);var n=t.id;if(l>n){if(0===l||l===n)return;var r=h[l];h[n]=r,r.id=n}},releaseNode:function(e){c>0&&(c-=1);var t=v[e.id];delete v[e.id],g.removeNode(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=d[c];d[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;c>t;++t){var n=d[t];e.x=n.position.x,e.y=-n.position.y,u&&u(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;l>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,s&&s(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):f=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-a[12])/a[0],e.y=(e.y-a[13])/a[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;c>n;++n)if(t(d[n],e.x,e.y))return d[n].node;return null}};return Viva.Graph.Utils.events(N).extend(),N},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},i=function(t){return e.getNodeAtClientPos(t,r)},o=null,a=[],u=[],s=[],f=[],c=[],l=[],d=[],h=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},p=function(e){return v(e),!1},m=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(e){var r={x:0,y:0},g=null,y=+new Date,x=function(e){m(c,[g,e]),r.x=e.clientX,r.y=e.clientY},w=function(){h.stop("mousemove",x),h.stop("mouseup",w)},V=function(){n=e.getBoundingClientRect()};window.addEventListener("resize",V),V(),e.addEventListener("mousemove",function(e){if(!o){var t,s=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,t=i(r),t&&g!==t?(g=t,s=s||m(a,[g])):null===t&&g!==t&&(s=s||m(u,[g]),g=null),s&&v(e)}}),e.addEventListener("mousedown",function(e){var o,a=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]?(a=m(s,o),h.on("mousemove",x),h.on("mouseup",w),t=window.document.onselectstart,window.document.onselectstart=p,g=o[0]):g=null,a&&v(e)}),e.addEventListener("mouseup",function(e){var o,a=+new Date;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]&&(window.document.onselectstart=t,400>a-y&&o[0]===g?m(d,o):m(l,o),y=a,m(f,o)&&v(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&l.push(e),this},dblClick:function(e){return"function"==typeof e&&d.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file diff --git a/unit_tests/test_constantLayout.js b/unit_tests/test_constantLayout.js index 46ade51..84579ad 100644 --- a/unit_tests/test_constantLayout.js +++ b/unit_tests/test_constantLayout.js @@ -12,9 +12,10 @@ var test_constantLayout = function(test) { layout.run(); graph.forEachNode(function(node) { - test.assert(node.hasOwnProperty('position'), 'All nodes expected to have some position'); - test.assert(typeof node.position.x === 'number', 'Node position does not have a valid x position'); - test.assert(typeof node.position.y === 'number', 'Node position does not have a valid y position'); + var position = layout.getNodePosition(node.id); + test.assert(position, 'All nodes expected to have some position'); + test.assert(typeof position.x === 'number', 'Node position does not have a valid x position'); + test.assert(typeof position.y === 'number', 'Node position does not have a valid y position'); }); }, @@ -29,8 +30,9 @@ var test_constantLayout = function(test) { layout.run(); graph.forEachNode(function(node) { - test.assertEqual(node.position.x, 42, 'Node position does not have a valid x position'); - test.assertEqual(node.position.y, 42, 'Node position does not have a valid y position'); + var position = layout.getNodePosition(node.id); + test.assertEqual(position.x, 42, 'Node position does not have a valid x position'); + test.assertEqual(position.y, 42, 'Node position does not have a valid y position'); }); }, @@ -45,8 +47,9 @@ var test_constantLayout = function(test) { layout.run(); graph.forEachNode(function(node) { - test.assert(node.position.x <= layoutSettings.maxX, 'Node position does not have a valid x position'); - test.assert(node.position.y <= layoutSettings.maxY, 'Node position does not have a valid y position'); + var position = layout.getNodePosition(node.id); + test.assert(position.x <= layoutSettings.maxX, 'Node position does not have a valid x position'); + test.assert(position.y <= layoutSettings.maxY, 'Node position does not have a valid y position'); }); } }; From 307cd3b60b8f89e118034e67fec61f48890fa39e Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 7 Sep 2013 23:50:08 -0700 Subject: [PATCH 032/276] Fixed a typo --- demos/other/webglInput.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demos/other/webglInput.html b/demos/other/webglInput.html index e6f9caa..7655d74 100644 --- a/demos/other/webglInput.html +++ b/demos/other/webglInput.html @@ -37,7 +37,7 @@ }).dblClick(function (node) { console.log('Double click on node: ' + node.id); }).click(function (node) { - console.log('Sincle click on node: ' + node.id); + console.log('Single click on node: ' + node.id); }); renderer.run(); From 7494739750c4fe716668fd8a6c71c2023e593820 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 7 Sep 2013 23:54:00 -0700 Subject: [PATCH 033/276] Updated pin node example --- demos/other/pinNode.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/demos/other/pinNode.html b/demos/other/pinNode.html index 4a847a9..3bc3a2d 100644 --- a/demos/other/pinNode.html +++ b/demos/other/pinNode.html @@ -35,7 +35,8 @@ .attr("height", 10) .attr("fill", "#00a2e8"); ui.addEventListener('click', function () { - node.isPinned = !node.isPinned + // toggle pinned mode + layout.pinNode(node, !layout.isNodePinned(node)); }); return ui; }); From 91d59c149a4b61b3d4815abf18bb392f77117084 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 8 Sep 2013 00:10:50 -0700 Subject: [PATCH 034/276] Removed invalid todo comment --- src/Layout/forceDirected.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Layout/forceDirected.js b/src/Layout/forceDirected.js index aa280ae..2f7a044 100644 --- a/src/Layout/forceDirected.js +++ b/src/Layout/forceDirected.js @@ -151,7 +151,6 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { toBody = getBody(link.toId), spring = forceSimulator.addSpring(fromBody, toBody, -1.0, link.weight); - // TODO: this has a bug, with multiple springs between same nodes springs[link.id] = spring; }, From 1dd2f26c7aa24b5535cfca1f5435d07efb702722 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 20 Oct 2013 20:18:12 -0700 Subject: [PATCH 035/276] Breaking change: addNode() graph.addNode() no longer augments prevous data model associated with node. Instead it stores direct reference to passed object --- src/Core/graph.js | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/src/Core/graph.js b/src/Core/graph.js index b0c5227..6bdf3a5 100644 --- a/src/Core/graph.js +++ b/src/Core/graph.js @@ -104,26 +104,7 @@ Viva.Graph.graph = function () { recordNodeChange(node, 'update'); } - if (data) { - var augmentedData = node.data || {}, - dataType = typeof data, - name; - - if (dataType === 'string' || isArray(data) || - dataType === 'number' || dataType === 'boolean') { - augmentedData = data; - } else if (dataType === 'undefined') { - augmentedData = null; - } else { - for (name in data) { - if (data.hasOwnProperty(name)) { - augmentedData[name] = data[name]; - } - } - } - - node.data = augmentedData; - } + node.data = data; nodes[nodeId] = node; From f3df359aa25189093bc53a85fbd779e86195cff0 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 20 Oct 2013 20:18:55 -0700 Subject: [PATCH 036/276] Proper node pin detection --- src/Layout/forceDirected.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Layout/forceDirected.js b/src/Layout/forceDirected.js index 2f7a044..0b66c4b 100644 --- a/src/Layout/forceDirected.js +++ b/src/Layout/forceDirected.js @@ -99,9 +99,7 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { body.mass = 1 + graph.getLinks(nodeId).length / 3.0; }, - isNodePinned = function(nodeId) { - var node = graph.getNode(nodeId); - + isNodePinned = function(node) { return (node && (node.isPinned || (node.data && node.data.isPinned))); }, From 4f05a1da84c6baa97f0a9db01fc07834087de95d Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 20 Oct 2013 20:19:48 -0700 Subject: [PATCH 037/276] Using Robert Jenkin's 32bit hash funciton as seeded prng --- dist/vivagraph.js | 145 +++++++----------------------------------- dist/vivagraph.min.js | 4 +- src/Utils/etc.js | 119 ++++++---------------------------- 3 files changed, 44 insertions(+), 224 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 43794a6..e001764 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -36,112 +36,33 @@ Viva.lazyExtend = function (target, options) { return target; }; /** - * Implenetation of seeded pseudo random number generator, based on LFIB4 algorithm. + * Implenetation of seeded pseudo random number generator, based on Robert Jenkin's 32 bit integer hash function * * Usage example: - * var random = Viva.random('random seed', 'can', 'be', 'multiple strings'), + * var random = Viva.random(seedNumber), * i = random.next(100); // returns random number from [0 .. 100) range. */ Viva.random = function () { - // From http://baagoe.com/en/RandomMusings/javascript/ - function getMash() { - var n = 0xefc8249d; - - var mash = function (data) { - var i; - data = data.toString(); - for (i = 0; i < data.length; i++) { - n += data.charCodeAt(i); - var h = 0.02519603282416938 * n; - n = h >>> 0; - h -= n; - h *= n; - n = h >>> 0; - h -= n; - n += h * 0x100000000; // 2^32 - } - return (n >>> 0) * 2.3283064365386963e-10; // 2^-32 - }; - - mash.version = 'Mash 0.9'; - return mash; + var firstArg = arguments[0]; + var seed; + if (typeof firstArg === 'number') { + seed = firstArg; + } else if (typeof firstArg === 'string') { + seed = firstArg.length; + } else { + seed = +new Date(); } - - function LFIB4(args) { - return (function (args) { - // George Marsaglia's LFIB4, - //http://groups.google.com/group/sci.crypt/msg/eb4ddde782b17051 - var k0 = 0, - k1 = 58, - k2 = 119, - k3 = 178, - j, - i, - s = [], - mash = getMash(); - - if (args.length === 0) { - args = [+new Date()]; - } - - for (j = 0; j < 256; j++) { - s[j] = mash(' '); - s[j] -= mash(' ') * 4.76837158203125e-7; // 2^-21 - if (s[j] < 0) { - s[j] += 1; - } - } - - for (i = 0; i < args.length; i++) { - for (j = 0; j < 256; j++) { - s[j] -= mash(args[i]); - s[j] -= mash(args[i]) * 4.76837158203125e-7; // 2^-21 - if (s[j] < 0) { - s[j] += 1; - } - } - } - - mash = null; - - var random = function () { - var x; - - k0 = (k0 + 1) & 255; - k1 = (k1 + 1) & 255; - k2 = (k2 + 1) & 255; - k3 = (k3 + 1) & 255; - - x = s[k0] - s[k1]; - if (x < 0) { - x += 1; - } - x -= s[k2]; - if (x < 0) { - x += 1; - } - x -= s[k3]; - if (x < 0) { - x += 1; - } - - s[k0] = x; - return x; - }; - - random.uint32 = function () { - return random() * 0x100000000 >>> 0; // 2^32 - }; - random.fract53 = random; - random.version = 'LFIB4 0.9'; - random.args = args; - - return random; - }(args)); - } - - var randomFunc = new LFIB4(Array.prototype.slice.call(arguments)); + var randomFunc = function() { + // Robert Jenkins' 32 bit integer hash function. + seed = ((seed + 0x7ed55d16) + (seed << 12)) & 0xffffffff; + seed = ((seed ^ 0xc761c23c) ^ (seed >>> 19)) & 0xffffffff; + seed = ((seed + 0x165667b1) + (seed << 5)) & 0xffffffff; + seed = ((seed + 0xd3a2646c) ^ (seed << 9)) & 0xffffffff; + seed = ((seed + 0xfd7046c5) + (seed << 3)) & 0xffffffff; + seed = ((seed ^ 0xb55a4f09) ^ (seed >>> 16)) & 0xffffffff; + return (seed & 0xfffffff) / 0x10000000; + }; return { /** @@ -1165,26 +1086,7 @@ Viva.Graph.graph = function () { recordNodeChange(node, 'update'); } - if (data) { - var augmentedData = node.data || {}, - dataType = typeof data, - name; - - if (dataType === 'string' || isArray(data) || - dataType === 'number' || dataType === 'boolean') { - augmentedData = data; - } else if (dataType === 'undefined') { - augmentedData = null; - } else { - for (name in data) { - if (data.hasOwnProperty(name)) { - augmentedData[name] = data[name]; - } - } - } - - node.data = augmentedData; - } + node.data = data; nodes[nodeId] = node; @@ -2283,9 +2185,7 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { body.mass = 1 + graph.getLinks(nodeId).length / 3.0; }, - isNodePinned = function(nodeId) { - var node = graph.getNode(nodeId); - + isNodePinned = function(node) { return (node && (node.isPinned || (node.data && node.data.isPinned))); }, @@ -2335,7 +2235,6 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { toBody = getBody(link.toId), spring = forceSimulator.addSpring(fromBody, toBody, -1.0, link.weight); - // TODO: this has a bug, with multiple springs between same nodes springs[link.id] = spring; }, diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 0bfb3ff..cc83815 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.0",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){function e(){var e=4022871197,t=function(t){var n;for(t=""+t,n=0;t.length>n;n++){e+=t.charCodeAt(n);var r=.02519603282416938*e;e=r>>>0,r-=e,r*=e,e=r>>>0,r-=e,e+=4294967296*r}return 2.3283064365386963e-10*(e>>>0)};return t.version="Mash 0.9",t}function t(t){return function(t){var n,r,i=0,o=58,a=119,u=178,s=[],f=e();for(0===t.length&&(t=[+new Date]),n=0;256>n;n++)s[n]=f(" "),s[n]-=4.76837158203125e-7*f(" "),0>s[n]&&(s[n]+=1);for(r=0;t.length>r;r++)for(n=0;256>n;n++)s[n]-=f(t[r]),s[n]-=4.76837158203125e-7*f(t[r]),0>s[n]&&(s[n]+=1);f=null;var c=function(){var e;return i=255&i+1,o=255&o+1,a=255&a+1,u=255&u+1,e=s[i]-s[o],0>e&&(e+=1),e-=s[a],0>e&&(e+=1),e-=s[u],0>e&&(e+=1),s[i]=e,e};return c.uint32=function(){return 4294967296*c()>>>0},c.fract53=c,c.version="LFIB4 0.9",c.args=t,c}(t)}var n=new t(Array.prototype.slice.call(arguments));return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,l=0,d=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-l,y:r-d}),l=t,d=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(l=e.clientX,d=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:l,y:d}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},P=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},N=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",P,!1):e.addEventListener("DOMMouseScroll",P,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",P,!1):e.removeEventListener("DOMMouseScroll",P,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),l=n.clientX,d=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:l,y:d}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),N(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,l,d,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,d=n*t-e*r,m=s*i+c*o+d,g=s*a+c*u+d,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,l=i-a,h=a*o-i*u,v=f*e+l*t+h,p=f*n+l*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*l-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-l*d,V.x=(0>w?w-x:w+x)/y,w=f*d-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var l=i(a);l===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=l}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},l=function(e){return e&&"object"==typeof e&&"number"==typeof e.length&&"function"==typeof e.splice&&!e.propertyIsEnumerable("length")},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);if(i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),n){var o,a=i.data||{},c=typeof n;if("string"===c||l(n)||"number"===c||"boolean"===c)a=n;else if("undefined"===c)a=null;else for(o in n)n.hasOwnProperty(o)&&(a[o]=n[o]);i.data=a}return e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),l=n.hasOwnProperty(f);(l||this.hasLink(e,r))&&(l||(n[f]=0),f+="@"+ ++n[f]);var d=new Viva.Graph.Link(e,r,i,f);return t.push(d),o.links.push(d),a.links.push(d),c(d,"add"),s(this),d},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,l=Math.sqrt(f*f+c*c);l>r&&(u.velocity.x=r*f/l,u.velocity.y=r*c/l),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,l=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},d=l(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(d,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=l(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,l=0,h=1;for(f[0]=d;c;){var v=f[l],p=v.body;c-=1,l+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,d=l(),d.left=n,d.right=i,d.top=r,d.bottom=o,t=u;t--;)v(a[t],d)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};i="number"==typeof i?i:1;var o=new Viva.Graph.Physics.Spring(e,t,n,r>=0?r:-1,i);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),f={},c=function(e){var n=(u.x1+u.x2)/2,r=(u.y1+u.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],a=o.fromId!==e.id?f[o.fromId]:f[o.toId];a&&a.location&&(n=a.location.x,r=a.location.y)}return{x:n+s.next(i)-i/2,y:r+s.next(i)-i/2}},l=function(e){return f[e]},d=function(e){f[e]=null,delete f[e]},h={},v=function(t){var n=l(t);n.mass=1+e.getLinks(t).length/3},p=function(t){var n=e.getNode(t);return n&&(n.isPinned||n.data&&n.data.isPinned)},m=function(e){return e.isPinned},g=function(t){var n=l(t);if(!n){var i=e.getNode(t);if(!i)return;n=new Viva.Graph.Physics.Body,f[t]=n;var o=c(i);n.loc(o),v(t),p(i)&&(n.isPinned=!0),r.addBody(n)}},y=function(e){g(e.id)},x=function(e){var t=l(e.id);t&&(d(e.id),r.removeBody(t))},w=function(e){v(e.fromId),v(e.toId);var t=l(e.fromId),n=l(e.toId),i=r.addSpring(t,n,-1,e.weight);h[e.id]=i},V=function(t){var n=h[t.id];if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&v(i.id),o&&v(o.id),delete h[t.id],r.removeSpring(n)}},b=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&g(n.node.id),n.link&&w(n.link)):"remove"===n.changeType&&(n.node&&x(n.node),n.link&&V(n.link))}},P=function(){e.forEachNode(y),e.forEachLink(w),e.addEventListener("changed",b)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in f)if(f.hasOwnProperty(o)){var a=f[o];m(a)?(a.location.x=a.prevLocation.x,a.location.y=a.prevLocation.y):(a.prevLocation.x=a.location.x,a.prevLocation.y=a.location.y),t>a.location.x&&(t=a.location.x),a.location.x>r&&(r=a.location.x),n>a.location.y&&(n=a.location.y),a.location.y>i&&(i=a.location.y)}u.x1=t,u.x2=r,u.y1=n,u.y2=i}};return r.setSpringForce(o),r.setNbodyForce(i),r.setDragForce(a),P(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(20);return N(),n>e},isNodePinned:function(e){var t=l(e.id);return t?m(t):void 0},pinNode:function(e,t){var n=l(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=l(e);return t||(g(e),t=l(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=l(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",b)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a={},u=function(e){e&&(a[e.id]||(a[e.id]=i(e)),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&u(n.node)}};return{run:function(){this.step()},step:function(){return s(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,l=!0,d=0,h=0,v=!1,p=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return v=u.step()&&!p,V(),!v},P=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(d=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},N=function(){v=!1,i.restart()},E=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),l=!1},L=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),p=!0,N()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),p=!0,V()},onStop:function(){u.pinNode(e,t),p=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),l&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(l=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},R=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);N()},D=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",R),o=null)},z=function(){x.on("resize",D),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){var r=Math.pow(1.4,0>t?-.2:.2);g.scale=s.scale(r,n),V(),w.fire("scale",g.scale)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",R)},B=function(){c=!1,O(),F(),x.stop("resize",D),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),E(),G(),C(),z(),c=!0),P(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},dispose:function(){B()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],l=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,l,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"}; -var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},l=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},d=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?l(e):(l=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,d()},translateRel:function(e,r){t+=e,n+=r,d()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,d()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),l=f.attr("id"),d=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&l===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&d===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i,o=1,a={},u={},s=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},f=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},c=function(){return Viva.Graph.svg("line").attr("stroke","#999")},l=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},d=function(e){e.fire("rescaled")},h={x:0,y:0},v={x:0,y:0},p={x:0,y:0},m=function(){if(e){var t="matrix("+o+", 0, 0,"+o+","+n+","+r+")";e.attr("transform",t)}},g={getNodeUI:function(e){return a[e]},getLinkUI:function(e){return u[e]},node:function(e){return"function"==typeof e?(s=e,this):void 0},link:function(e){return"function"==typeof e?(c=e,this):void 0},placeNode:function(e){return f=e,this},placeLink:function(e){return l=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,m()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(i,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(i).translate(-u.x,-u.y),f=e.getCTM().multiply(s);o=f.a,n=f.e,r=f.f;var c="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",c),d(this),o},resetScale:function(){o=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),d(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),m(),"function"==typeof i&&i(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(t,n){var r=c(t);if(r)return r.position=n,r.link=t,u[t.id]=r,e.childElementCount>0?e.insertBefore(r,e.firstChild):e.appendChild(r),r},releaseLink:function(t){var n=u[t.id];n&&(e.removeChild(n),delete u[t.id])},addNode:function(t,n){var r=s(t);if(r)return r.position=n,r.node=t,a[t.id]=r,e.appendChild(r),r},releaseNode:function(t){var n=a[t.id];n&&(e.removeChild(n),delete a[t.id])},renderNodes:function(){for(var e in a)if(a.hasOwnProperty(e)){var t=a[e];h.x=t.position.x,h.y=t.position.y,f(t,h,t.node)}},renderLinks:function(){for(var e in u)if(u.hasOwnProperty(e)){var t=u[e];v.x=t.position.from.x,v.y=t.position.from.y,p.x=t.position.to.x,p.y=t.position.to.y,l(t,v,p,t.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):i=e),t},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(g).extend(),g},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,l=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(l.x)+" "+Math.round(l.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),d=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),v=new Float32Array(h),p=new Uint32Array(h),m=0,g=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(p),v=t,p=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(d,l),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;v[n*f]=t.x,v[n*f+1]=t.y,v[n*f+2]=e.size,p[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(p,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),v=0,p=new ArrayBuffer(16*l),m=new Float32Array(p),g=new Uint32Array(p),y=function(){if((v+1)*l>p.byteLength){var e=new ArrayBuffer(2*p.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,p=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,d),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),v+=1,o=e.id},removeLink:function(e){v>0&&(v-=1),v>e.id&&v>0&&r.copyArrayPart(g,e.id*c,v*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,p,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*v),o=v-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},l=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},d=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},v=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},p=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=d(e),o={offset:e};r.textureNumber>=s.length&&l();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=d(t.offset),r=d(o);p(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],v(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){v(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,l=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),d=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,v=0,p=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(d,l),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;p[n]=t.x-e.size,p[n+1]=t.y-e.size,p[n+2]=4*e._offset,p[n+3]=t.x+e.size,p[n+4]=t.y-e.size,p[n+5]=4*e._offset+1,p[n+6]=t.x-e.size,p[n+7]=t.y+e.size,p[n+8]=4*e._offset+2,p[n+9]=t.x-e.size,p[n+10]=t.y+e.size,p[n+11]=4*e._offset+2,p[n+12]=t.x+e.size,p[n+13]=t.y-e.size,p[n+14]=4*e._offset+1,p[n+15]=t.x+e.size,p[n+16]=t.y+e.size,p[n+17]=4*e._offset+3},createNode:function(t){p=i.extendArray(p,v,c),v+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){v>0&&(v-=1),v>t.id&&v>0&&(t.src&&e.remove(t.src),i.copyArrayPart(p,t.id*c,v*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,p,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*v)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f,c=0,l=0,d=[],h=[],v={},p={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(a),g.updateTransform(a)},V=function(){a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},P=function(e){e.fire("rescaled")},N={getLinkUI:function(e){return p[e]},getNodeUI:function(e){return v[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return u=e,this},placeLink:function(e){return s=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){l>0&&m.render(),c>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(){b()},addLink:function(e,t){var n=l++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,p[e.id]=r,r},addNode:function(e,t){var n=c++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),d[n]=r,v[e.id]=r,r},translateRel:function(e,t){a[12]+=2*a[0]*e/i/a[0],a[13]-=2*a[5]*t/o/a[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=a[12],r-=a[13],a[12]+=n*(1-e),a[13]+=r*(1-e),a[0]*=e,a[5]*=e,w(),P(this),a[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var s="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(s),s}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof f&&f(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){l>0&&(l-=1);var t=p[e.id];delete p[e.id],m.removeLink(t);var n=t.id;if(l>n){if(0===l||l===n)return;var r=h[l];h[n]=r,r.id=n}},releaseNode:function(e){c>0&&(c-=1);var t=v[e.id];delete v[e.id],g.removeNode(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=d[c];d[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;c>t;++t){var n=d[t];e.x=n.position.x,e.y=-n.position.y,u&&u(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;l>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,s&&s(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):f=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-a[12])/a[0],e.y=(e.y-a[13])/a[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;c>n;++n)if(t(d[n],e.x,e.y))return d[n].node;return null}};return Viva.Graph.Utils.events(N).extend(),N},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},i=function(t){return e.getNodeAtClientPos(t,r)},o=null,a=[],u=[],s=[],f=[],c=[],l=[],d=[],h=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},p=function(e){return v(e),!1},m=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(e){var r={x:0,y:0},g=null,y=+new Date,x=function(e){m(c,[g,e]),r.x=e.clientX,r.y=e.clientY},w=function(){h.stop("mousemove",x),h.stop("mouseup",w)},V=function(){n=e.getBoundingClientRect()};window.addEventListener("resize",V),V(),e.addEventListener("mousemove",function(e){if(!o){var t,s=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,t=i(r),t&&g!==t?(g=t,s=s||m(a,[g])):null===t&&g!==t&&(s=s||m(u,[g]),g=null),s&&v(e)}}),e.addEventListener("mousedown",function(e){var o,a=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]?(a=m(s,o),h.on("mousemove",x),h.on("mouseup",w),t=window.document.onselectstart,window.document.onselectstart=p,g=o[0]):g=null,a&&v(e)}),e.addEventListener("mouseup",function(e){var o,a=+new Date;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]&&(window.document.onselectstart=t,400>a-y&&o[0]===g?m(d,o):m(l,o),y=a,m(f,o)&&v(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&l.push(e),this},dblClick:function(e){return"function"==typeof e&&d.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file +var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.0",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},P=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},N=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",P,!1):e.addEventListener("DOMMouseScroll",P,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",P,!1):e.removeEventListener("DOMMouseScroll",P,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),N(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,d=Math.sqrt(f*f+c*c);d>r&&(u.velocity.x=r*f/d,u.velocity.y=r*c/d),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};i="number"==typeof i?i:1;var o=new Viva.Graph.Physics.Spring(e,t,n,r>=0?r:-1,i);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),f={},c=function(e){var n=(u.x1+u.x2)/2,r=(u.y1+u.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],a=o.fromId!==e.id?f[o.fromId]:f[o.toId];a&&a.location&&(n=a.location.x,r=a.location.y)}return{x:n+s.next(i)-i/2,y:r+s.next(i)-i/2}},d=function(e){return f[e]},l=function(e){f[e]=null,delete f[e]},h={},v=function(t){var n=d(t);n.mass=1+e.getLinks(t).length/3},p=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},m=function(e){return e.isPinned},g=function(t){var n=d(t);if(!n){var i=e.getNode(t);if(!i)return;n=new Viva.Graph.Physics.Body,f[t]=n;var o=c(i);n.loc(o),v(t),p(i)&&(n.isPinned=!0),r.addBody(n)}},y=function(e){g(e.id)},x=function(e){var t=d(e.id);t&&(l(e.id),r.removeBody(t))},w=function(e){v(e.fromId),v(e.toId);var t=d(e.fromId),n=d(e.toId),i=r.addSpring(t,n,-1,e.weight);h[e.id]=i},V=function(t){var n=h[t.id];if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&v(i.id),o&&v(o.id),delete h[t.id],r.removeSpring(n)}},b=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&g(n.node.id),n.link&&w(n.link)):"remove"===n.changeType&&(n.node&&x(n.node),n.link&&V(n.link))}},P=function(){e.forEachNode(y),e.forEachLink(w),e.addEventListener("changed",b)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in f)if(f.hasOwnProperty(o)){var a=f[o];m(a)?(a.location.x=a.prevLocation.x,a.location.y=a.prevLocation.y):(a.prevLocation.x=a.location.x,a.prevLocation.y=a.location.y),t>a.location.x&&(t=a.location.x),a.location.x>r&&(r=a.location.x),n>a.location.y&&(n=a.location.y),a.location.y>i&&(i=a.location.y)}u.x1=t,u.x2=r,u.y1=n,u.y2=i}};return r.setSpringForce(o),r.setNbodyForce(i),r.setDragForce(a),P(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(20);return N(),n>e},isNodePinned:function(e){var t=d(e.id);return t?m(t):void 0},pinNode:function(e,t){var n=d(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=d(e);return t||(g(e),t=d(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=d(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",b)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a={},u=function(e){e&&(a[e.id]||(a[e.id]=i(e)),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&u(n.node)}};return{run:function(){this.step()},step:function(){return s(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,d=!0,l=0,h=0,v=!1,p=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return v=u.step()&&!p,V(),!v},P=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(l=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},N=function(){v=!1,i.restart()},E=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),d=!1},L=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),p=!0,N()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),p=!0,V()},onStop:function(){u.pinNode(e,t),p=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),d&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(d=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},R=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);N()},D=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",R),o=null)},z=function(){x.on("resize",D),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){var r=Math.pow(1.4,0>t?-.2:.2);g.scale=s.scale(r,n),V(),w.fire("scale",g.scale)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",R)},B=function(){c=!1,O(),F(),x.stop("resize",D),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),E(),G(),C(),z(),c=!0),P(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},dispose:function(){B()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e); +for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},d=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},l=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?d(e):(d=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,l()},translateRel:function(e,r){t+=e,n+=r,l()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,l()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),d=f.attr("id"),l=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&d===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&l===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i,o=1,a={},u={},s=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},f=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},c=function(){return Viva.Graph.svg("line").attr("stroke","#999")},d=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},l=function(e){e.fire("rescaled")},h={x:0,y:0},v={x:0,y:0},p={x:0,y:0},m=function(){if(e){var t="matrix("+o+", 0, 0,"+o+","+n+","+r+")";e.attr("transform",t)}},g={getNodeUI:function(e){return a[e]},getLinkUI:function(e){return u[e]},node:function(e){return"function"==typeof e?(s=e,this):void 0},link:function(e){return"function"==typeof e?(c=e,this):void 0},placeNode:function(e){return f=e,this},placeLink:function(e){return d=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,m()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(i,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(i).translate(-u.x,-u.y),f=e.getCTM().multiply(s);o=f.a,n=f.e,r=f.f;var c="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",c),l(this),o},resetScale:function(){o=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),l(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),m(),"function"==typeof i&&i(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(t,n){var r=c(t);if(r)return r.position=n,r.link=t,u[t.id]=r,e.childElementCount>0?e.insertBefore(r,e.firstChild):e.appendChild(r),r},releaseLink:function(t){var n=u[t.id];n&&(e.removeChild(n),delete u[t.id])},addNode:function(t,n){var r=s(t);if(r)return r.position=n,r.node=t,a[t.id]=r,e.appendChild(r),r},releaseNode:function(t){var n=a[t.id];n&&(e.removeChild(n),delete a[t.id])},renderNodes:function(){for(var e in a)if(a.hasOwnProperty(e)){var t=a[e];h.x=t.position.x,h.y=t.position.y,f(t,h,t.node)}},renderLinks:function(){for(var e in u)if(u.hasOwnProperty(e)){var t=u[e];v.x=t.position.from.x,v.y=t.position.from.y,p.x=t.position.to.x,p.y=t.position.to.y,d(t,v,p,t.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):i=e),t},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(g).extend(),g},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,d=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(d.x)+" "+Math.round(d.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),l=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),v=new Float32Array(h),p=new Uint32Array(h),m=0,g=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(p),v=t,p=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(l,d),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;v[n*f]=t.x,v[n*f+1]=t.y,v[n*f+2]=e.size,p[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(p,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,d=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),v=0,p=new ArrayBuffer(16*d),m=new Float32Array(p),g=new Uint32Array(p),y=function(){if((v+1)*d>p.byteLength){var e=new ArrayBuffer(2*p.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,p=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,l),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),v+=1,o=e.id},removeLink:function(e){v>0&&(v-=1),v>e.id&&v>0&&r.copyArrayPart(g,e.id*c,v*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,p,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*v),o=v-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},d=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},l=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},v=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},p=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=l(e),o={offset:e};r.textureNumber>=s.length&&d();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=l(t.offset),r=l(o);p(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],v(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){v(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,d=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),l=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,v=0,p=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(l,d),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;p[n]=t.x-e.size,p[n+1]=t.y-e.size,p[n+2]=4*e._offset,p[n+3]=t.x+e.size,p[n+4]=t.y-e.size,p[n+5]=4*e._offset+1,p[n+6]=t.x-e.size,p[n+7]=t.y+e.size,p[n+8]=4*e._offset+2,p[n+9]=t.x-e.size,p[n+10]=t.y+e.size,p[n+11]=4*e._offset+2,p[n+12]=t.x+e.size,p[n+13]=t.y-e.size,p[n+14]=4*e._offset+1,p[n+15]=t.x+e.size,p[n+16]=t.y+e.size,p[n+17]=4*e._offset+3},createNode:function(t){p=i.extendArray(p,v,c),v+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){v>0&&(v-=1),v>t.id&&v>0&&(t.src&&e.remove(t.src),i.copyArrayPart(p,t.id*c,v*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,p,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*v)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f,c=0,d=0,l=[],h=[],v={},p={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(a),g.updateTransform(a)},V=function(){a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},P=function(e){e.fire("rescaled")},N={getLinkUI:function(e){return p[e]},getNodeUI:function(e){return v[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return u=e,this},placeLink:function(e){return s=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){d>0&&m.render(),c>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(){b()},addLink:function(e,t){var n=d++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,p[e.id]=r,r},addNode:function(e,t){var n=c++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),l[n]=r,v[e.id]=r,r},translateRel:function(e,t){a[12]+=2*a[0]*e/i/a[0],a[13]-=2*a[5]*t/o/a[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=a[12],r-=a[13],a[12]+=n*(1-e),a[13]+=r*(1-e),a[0]*=e,a[5]*=e,w(),P(this),a[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var s="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(s),s}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof f&&f(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){d>0&&(d-=1);var t=p[e.id];delete p[e.id],m.removeLink(t);var n=t.id;if(d>n){if(0===d||d===n)return;var r=h[d];h[n]=r,r.id=n}},releaseNode:function(e){c>0&&(c-=1);var t=v[e.id];delete v[e.id],g.removeNode(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=l[c];l[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;c>t;++t){var n=l[t];e.x=n.position.x,e.y=-n.position.y,u&&u(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;d>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,s&&s(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):f=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-a[12])/a[0],e.y=(e.y-a[13])/a[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;c>n;++n)if(t(l[n],e.x,e.y))return l[n].node;return null}};return Viva.Graph.Utils.events(N).extend(),N},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},i=function(t){return e.getNodeAtClientPos(t,r)},o=null,a=[],u=[],s=[],f=[],c=[],d=[],l=[],h=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},p=function(e){return v(e),!1},m=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(e){var r={x:0,y:0},g=null,y=+new Date,x=function(e){m(c,[g,e]),r.x=e.clientX,r.y=e.clientY},w=function(){h.stop("mousemove",x),h.stop("mouseup",w)},V=function(){n=e.getBoundingClientRect()};window.addEventListener("resize",V),V(),e.addEventListener("mousemove",function(e){if(!o){var t,s=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,t=i(r),t&&g!==t?(g=t,s=s||m(a,[g])):null===t&&g!==t&&(s=s||m(u,[g]),g=null),s&&v(e)}}),e.addEventListener("mousedown",function(e){var o,a=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]?(a=m(s,o),h.on("mousemove",x),h.on("mouseup",w),t=window.document.onselectstart,window.document.onselectstart=p,g=o[0]):g=null,a&&v(e)}),e.addEventListener("mouseup",function(e){var o,a=+new Date;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]&&(window.document.onselectstart=t,400>a-y&&o[0]===g?m(l,o):m(d,o),y=a,m(f,o)&&v(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&l.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file diff --git a/src/Utils/etc.js b/src/Utils/etc.js index 90dca2a..2fcd74b 100644 --- a/src/Utils/etc.js +++ b/src/Utils/etc.js @@ -26,112 +26,33 @@ Viva.lazyExtend = function (target, options) { return target; }; /** - * Implenetation of seeded pseudo random number generator, based on LFIB4 algorithm. + * Implenetation of seeded pseudo random number generator, based on Robert Jenkin's 32 bit integer hash function * * Usage example: - * var random = Viva.random('random seed', 'can', 'be', 'multiple strings'), + * var random = Viva.random(seedNumber), * i = random.next(100); // returns random number from [0 .. 100) range. */ Viva.random = function () { - // From http://baagoe.com/en/RandomMusings/javascript/ - function getMash() { - var n = 0xefc8249d; - - var mash = function (data) { - var i; - data = data.toString(); - for (i = 0; i < data.length; i++) { - n += data.charCodeAt(i); - var h = 0.02519603282416938 * n; - n = h >>> 0; - h -= n; - h *= n; - n = h >>> 0; - h -= n; - n += h * 0x100000000; // 2^32 - } - return (n >>> 0) * 2.3283064365386963e-10; // 2^-32 - }; - - mash.version = 'Mash 0.9'; - return mash; - } - - function LFIB4(args) { - return (function (args) { - // George Marsaglia's LFIB4, - //http://groups.google.com/group/sci.crypt/msg/eb4ddde782b17051 - var k0 = 0, - k1 = 58, - k2 = 119, - k3 = 178, - j, - i, - s = [], - mash = getMash(); - - if (args.length === 0) { - args = [+new Date()]; - } - - for (j = 0; j < 256; j++) { - s[j] = mash(' '); - s[j] -= mash(' ') * 4.76837158203125e-7; // 2^-21 - if (s[j] < 0) { - s[j] += 1; - } - } - - for (i = 0; i < args.length; i++) { - for (j = 0; j < 256; j++) { - s[j] -= mash(args[i]); - s[j] -= mash(args[i]) * 4.76837158203125e-7; // 2^-21 - if (s[j] < 0) { - s[j] += 1; - } - } - } - - mash = null; - - var random = function () { - var x; - - k0 = (k0 + 1) & 255; - k1 = (k1 + 1) & 255; - k2 = (k2 + 1) & 255; - k3 = (k3 + 1) & 255; - - x = s[k0] - s[k1]; - if (x < 0) { - x += 1; - } - x -= s[k2]; - if (x < 0) { - x += 1; - } - x -= s[k3]; - if (x < 0) { - x += 1; - } - - s[k0] = x; - return x; - }; - - random.uint32 = function () { - return random() * 0x100000000 >>> 0; // 2^32 - }; - random.fract53 = random; - random.version = 'LFIB4 0.9'; - random.args = args; - - return random; - }(args)); + var firstArg = arguments[0]; + var seed; + if (typeof firstArg === 'number') { + seed = firstArg; + } else if (typeof firstArg === 'string') { + seed = firstArg.length; + } else { + seed = +new Date(); } - - var randomFunc = new LFIB4(Array.prototype.slice.call(arguments)); + var randomFunc = function() { + // Robert Jenkins' 32 bit integer hash function. + seed = ((seed + 0x7ed55d16) + (seed << 12)) & 0xffffffff; + seed = ((seed ^ 0xc761c23c) ^ (seed >>> 19)) & 0xffffffff; + seed = ((seed + 0x165667b1) + (seed << 5)) & 0xffffffff; + seed = ((seed + 0xd3a2646c) ^ (seed << 9)) & 0xffffffff; + seed = ((seed + 0xfd7046c5) + (seed << 3)) & 0xffffffff; + seed = ((seed ^ 0xb55a4f09) ^ (seed >>> 16)) & 0xffffffff; + return (seed & 0xfffffff) / 0x10000000; + }; return { /** From f334ae9e4549ae2ec8d09ed26d491ac540c6b5a3 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 20 Oct 2013 20:24:16 -0700 Subject: [PATCH 038/276] Updated changelog --- CHANGELOG | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 131a70d..a83e7fb 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,14 @@ +v0.5.0 + data: Oct 20, 2013 + BREAKING CHANGES: + - graph.addNode() no longer augments old data model with whatever passed + to method. Instead it stores direct reference to passed node's model + - node/link objects no longer store layout specific properties. Instead you can + query all layout properties from layout class itself. This allows the same + graph to be layed out by two different layout algorithm, without stepping + on toes of each other + - node/link objects no longer store ui specific properties. Instead you + can query them from specific UI provider v0.4.1 data: Jul 20, 2013 changes: From 5a33c31a4e0b85c2f221c033fbe4c3e18afc66fa Mon Sep 17 00:00:00 2001 From: Andrei Kashcha Date: Sun, 20 Oct 2013 20:26:20 -0700 Subject: [PATCH 039/276] Update CHANGELOG --- CHANGELOG | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index a83e7fb..aec8da3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,14 +1,14 @@ v0.5.0 data: Oct 20, 2013 - BREAKING CHANGES: - - graph.addNode() no longer augments old data model with whatever passed - to method. Instead it stores direct reference to passed node's model - - node/link objects no longer store layout specific properties. Instead you can - query all layout properties from layout class itself. This allows the same - graph to be layed out by two different layout algorithm, without stepping - on toes of each other - - node/link objects no longer store ui specific properties. Instead you - can query them from specific UI provider + BREAKING CHANGES: + - graph.addNode() no longer augments old data model with whatever passed + to method. Instead it stores direct reference to passed node's model + - node/link objects no longer store layout specific properties. Instead you can + query all layout properties from layout class itself. This allows the same + graph to be layed out by two different layout algorithm, without stepping + on toes of each other + - node/link objects no longer store ui specific properties. Instead you + can query them from specific UI provider v0.4.1 data: Jul 20, 2013 changes: From 2fcbc493c740a1a72ad3fb8a02761dc11979163b Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 26 Oct 2013 01:02:08 -0700 Subject: [PATCH 040/276] Using position if it was present on node --- dist/vivagraph.js | 3 +++ dist/vivagraph.min.js | 4 ++-- src/Layout/forceDirected.js | 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index e001764..8931168 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -2150,6 +2150,9 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { // TODO: Initial position could be picked better, e.g. take into // account all neighbouring nodes/links, not only one. // How about center of mass? + if (node.position) { + return node.position; + } var baseX = (graphRect.x1 + graphRect.x2) / 2, baseY = (graphRect.y1 + graphRect.y2) / 2, springLength = settings.springLength; diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index cc83815..e4f9564 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.0",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},P=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},N=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",P,!1):e.addEventListener("DOMMouseScroll",P,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",P,!1):e.removeEventListener("DOMMouseScroll",P,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),N(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,d=Math.sqrt(f*f+c*c);d>r&&(u.velocity.x=r*f/d,u.velocity.y=r*c/d),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};i="number"==typeof i?i:1;var o=new Viva.Graph.Physics.Spring(e,t,n,r>=0?r:-1,i);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),f={},c=function(e){var n=(u.x1+u.x2)/2,r=(u.y1+u.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],a=o.fromId!==e.id?f[o.fromId]:f[o.toId];a&&a.location&&(n=a.location.x,r=a.location.y)}return{x:n+s.next(i)-i/2,y:r+s.next(i)-i/2}},d=function(e){return f[e]},l=function(e){f[e]=null,delete f[e]},h={},v=function(t){var n=d(t);n.mass=1+e.getLinks(t).length/3},p=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},m=function(e){return e.isPinned},g=function(t){var n=d(t);if(!n){var i=e.getNode(t);if(!i)return;n=new Viva.Graph.Physics.Body,f[t]=n;var o=c(i);n.loc(o),v(t),p(i)&&(n.isPinned=!0),r.addBody(n)}},y=function(e){g(e.id)},x=function(e){var t=d(e.id);t&&(l(e.id),r.removeBody(t))},w=function(e){v(e.fromId),v(e.toId);var t=d(e.fromId),n=d(e.toId),i=r.addSpring(t,n,-1,e.weight);h[e.id]=i},V=function(t){var n=h[t.id];if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&v(i.id),o&&v(o.id),delete h[t.id],r.removeSpring(n)}},b=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&g(n.node.id),n.link&&w(n.link)):"remove"===n.changeType&&(n.node&&x(n.node),n.link&&V(n.link))}},P=function(){e.forEachNode(y),e.forEachLink(w),e.addEventListener("changed",b)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in f)if(f.hasOwnProperty(o)){var a=f[o];m(a)?(a.location.x=a.prevLocation.x,a.location.y=a.prevLocation.y):(a.prevLocation.x=a.location.x,a.prevLocation.y=a.location.y),t>a.location.x&&(t=a.location.x),a.location.x>r&&(r=a.location.x),n>a.location.y&&(n=a.location.y),a.location.y>i&&(i=a.location.y)}u.x1=t,u.x2=r,u.y1=n,u.y2=i}};return r.setSpringForce(o),r.setNbodyForce(i),r.setDragForce(a),P(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(20);return N(),n>e},isNodePinned:function(e){var t=d(e.id);return t?m(t):void 0},pinNode:function(e,t){var n=d(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=d(e);return t||(g(e),t=d(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=d(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",b)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a={},u=function(e){e&&(a[e.id]||(a[e.id]=i(e)),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&u(n.node)}};return{run:function(){this.step()},step:function(){return s(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,d=!0,l=0,h=0,v=!1,p=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return v=u.step()&&!p,V(),!v},P=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(l=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},N=function(){v=!1,i.restart()},E=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),d=!1},L=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),p=!0,N()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),p=!0,V()},onStop:function(){u.pinNode(e,t),p=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),d&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(d=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},R=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);N()},D=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",R),o=null)},z=function(){x.on("resize",D),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){var r=Math.pow(1.4,0>t?-.2:.2);g.scale=s.scale(r,n),V(),w.fire("scale",g.scale)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",R)},B=function(){c=!1,O(),F(),x.stop("resize",D),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),E(),G(),C(),z(),c=!0),P(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},dispose:function(){B()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e); -for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},d=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},l=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?d(e):(d=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,l()},translateRel:function(e,r){t+=e,n+=r,l()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,l()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),d=f.attr("id"),l=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&d===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&l===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i,o=1,a={},u={},s=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},f=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},c=function(){return Viva.Graph.svg("line").attr("stroke","#999")},d=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},l=function(e){e.fire("rescaled")},h={x:0,y:0},v={x:0,y:0},p={x:0,y:0},m=function(){if(e){var t="matrix("+o+", 0, 0,"+o+","+n+","+r+")";e.attr("transform",t)}},g={getNodeUI:function(e){return a[e]},getLinkUI:function(e){return u[e]},node:function(e){return"function"==typeof e?(s=e,this):void 0},link:function(e){return"function"==typeof e?(c=e,this):void 0},placeNode:function(e){return f=e,this},placeLink:function(e){return d=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,m()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(i,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(i).translate(-u.x,-u.y),f=e.getCTM().multiply(s);o=f.a,n=f.e,r=f.f;var c="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",c),l(this),o},resetScale:function(){o=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),l(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),m(),"function"==typeof i&&i(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(t,n){var r=c(t);if(r)return r.position=n,r.link=t,u[t.id]=r,e.childElementCount>0?e.insertBefore(r,e.firstChild):e.appendChild(r),r},releaseLink:function(t){var n=u[t.id];n&&(e.removeChild(n),delete u[t.id])},addNode:function(t,n){var r=s(t);if(r)return r.position=n,r.node=t,a[t.id]=r,e.appendChild(r),r},releaseNode:function(t){var n=a[t.id];n&&(e.removeChild(n),delete a[t.id])},renderNodes:function(){for(var e in a)if(a.hasOwnProperty(e)){var t=a[e];h.x=t.position.x,h.y=t.position.y,f(t,h,t.node)}},renderLinks:function(){for(var e in u)if(u.hasOwnProperty(e)){var t=u[e];v.x=t.position.from.x,v.y=t.position.from.y,p.x=t.position.to.x,p.y=t.position.to.y,d(t,v,p,t.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):i=e),t},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(g).extend(),g},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,d=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(d.x)+" "+Math.round(d.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),l=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),v=new Float32Array(h),p=new Uint32Array(h),m=0,g=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(p),v=t,p=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(l,d),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;v[n*f]=t.x,v[n*f+1]=t.y,v[n*f+2]=e.size,p[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(p,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,d=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),v=0,p=new ArrayBuffer(16*d),m=new Float32Array(p),g=new Uint32Array(p),y=function(){if((v+1)*d>p.byteLength){var e=new ArrayBuffer(2*p.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,p=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,l),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),v+=1,o=e.id},removeLink:function(e){v>0&&(v-=1),v>e.id&&v>0&&r.copyArrayPart(g,e.id*c,v*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,p,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*v),o=v-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},d=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},l=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},v=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},p=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=l(e),o={offset:e};r.textureNumber>=s.length&&d();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=l(t.offset),r=l(o);p(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],v(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){v(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,d=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),l=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,v=0,p=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(l,d),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;p[n]=t.x-e.size,p[n+1]=t.y-e.size,p[n+2]=4*e._offset,p[n+3]=t.x+e.size,p[n+4]=t.y-e.size,p[n+5]=4*e._offset+1,p[n+6]=t.x-e.size,p[n+7]=t.y+e.size,p[n+8]=4*e._offset+2,p[n+9]=t.x-e.size,p[n+10]=t.y+e.size,p[n+11]=4*e._offset+2,p[n+12]=t.x+e.size,p[n+13]=t.y-e.size,p[n+14]=4*e._offset+1,p[n+15]=t.x+e.size,p[n+16]=t.y+e.size,p[n+17]=4*e._offset+3},createNode:function(t){p=i.extendArray(p,v,c),v+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){v>0&&(v-=1),v>t.id&&v>0&&(t.src&&e.remove(t.src),i.copyArrayPart(p,t.id*c,v*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,p,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*v)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f,c=0,d=0,l=[],h=[],v={},p={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(a),g.updateTransform(a)},V=function(){a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},P=function(e){e.fire("rescaled")},N={getLinkUI:function(e){return p[e]},getNodeUI:function(e){return v[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return u=e,this},placeLink:function(e){return s=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){d>0&&m.render(),c>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(){b()},addLink:function(e,t){var n=d++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,p[e.id]=r,r},addNode:function(e,t){var n=c++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),l[n]=r,v[e.id]=r,r},translateRel:function(e,t){a[12]+=2*a[0]*e/i/a[0],a[13]-=2*a[5]*t/o/a[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=a[12],r-=a[13],a[12]+=n*(1-e),a[13]+=r*(1-e),a[0]*=e,a[5]*=e,w(),P(this),a[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var s="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(s),s}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof f&&f(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){d>0&&(d-=1);var t=p[e.id];delete p[e.id],m.removeLink(t);var n=t.id;if(d>n){if(0===d||d===n)return;var r=h[d];h[n]=r,r.id=n}},releaseNode:function(e){c>0&&(c-=1);var t=v[e.id];delete v[e.id],g.removeNode(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=l[c];l[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;c>t;++t){var n=l[t];e.x=n.position.x,e.y=-n.position.y,u&&u(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;d>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,s&&s(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):f=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-a[12])/a[0],e.y=(e.y-a[13])/a[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;c>n;++n)if(t(l[n],e.x,e.y))return l[n].node;return null}};return Viva.Graph.Utils.events(N).extend(),N},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},i=function(t){return e.getNodeAtClientPos(t,r)},o=null,a=[],u=[],s=[],f=[],c=[],d=[],l=[],h=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},p=function(e){return v(e),!1},m=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(e){var r={x:0,y:0},g=null,y=+new Date,x=function(e){m(c,[g,e]),r.x=e.clientX,r.y=e.clientY},w=function(){h.stop("mousemove",x),h.stop("mouseup",w)},V=function(){n=e.getBoundingClientRect()};window.addEventListener("resize",V),V(),e.addEventListener("mousemove",function(e){if(!o){var t,s=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,t=i(r),t&&g!==t?(g=t,s=s||m(a,[g])):null===t&&g!==t&&(s=s||m(u,[g]),g=null),s&&v(e)}}),e.addEventListener("mousedown",function(e){var o,a=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]?(a=m(s,o),h.on("mousemove",x),h.on("mouseup",w),t=window.document.onselectstart,window.document.onselectstart=p,g=o[0]):g=null,a&&v(e)}),e.addEventListener("mouseup",function(e){var o,a=+new Date;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]&&(window.document.onselectstart=t,400>a-y&&o[0]===g?m(l,o):m(d,o),y=a,m(f,o)&&v(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&l.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file +var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.0",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},P=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},N=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",P,!1):e.addEventListener("DOMMouseScroll",P,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",P,!1):e.removeEventListener("DOMMouseScroll",P,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),N(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,d=Math.sqrt(f*f+c*c);d>r&&(u.velocity.x=r*f/d,u.velocity.y=r*c/d),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};i="number"==typeof i?i:1;var o=new Viva.Graph.Physics.Spring(e,t,n,r>=0?r:-1,i);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),f={},c=function(e){if(e.position)return e.position;var n=(u.x1+u.x2)/2,r=(u.y1+u.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],a=o.fromId!==e.id?f[o.fromId]:f[o.toId];a&&a.location&&(n=a.location.x,r=a.location.y)}return{x:n+s.next(i)-i/2,y:r+s.next(i)-i/2}},d=function(e){return f[e]},l=function(e){f[e]=null,delete f[e]},h={},v=function(t){var n=d(t);n.mass=1+e.getLinks(t).length/3},p=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},m=function(e){return e.isPinned},g=function(t){var n=d(t);if(!n){var i=e.getNode(t);if(!i)return;n=new Viva.Graph.Physics.Body,f[t]=n;var o=c(i);n.loc(o),v(t),p(i)&&(n.isPinned=!0),r.addBody(n)}},y=function(e){g(e.id)},x=function(e){var t=d(e.id);t&&(l(e.id),r.removeBody(t))},w=function(e){v(e.fromId),v(e.toId);var t=d(e.fromId),n=d(e.toId),i=r.addSpring(t,n,-1,e.weight);h[e.id]=i},V=function(t){var n=h[t.id];if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&v(i.id),o&&v(o.id),delete h[t.id],r.removeSpring(n)}},b=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&g(n.node.id),n.link&&w(n.link)):"remove"===n.changeType&&(n.node&&x(n.node),n.link&&V(n.link))}},P=function(){e.forEachNode(y),e.forEachLink(w),e.addEventListener("changed",b)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in f)if(f.hasOwnProperty(o)){var a=f[o];m(a)?(a.location.x=a.prevLocation.x,a.location.y=a.prevLocation.y):(a.prevLocation.x=a.location.x,a.prevLocation.y=a.location.y),t>a.location.x&&(t=a.location.x),a.location.x>r&&(r=a.location.x),n>a.location.y&&(n=a.location.y),a.location.y>i&&(i=a.location.y)}u.x1=t,u.x2=r,u.y1=n,u.y2=i}};return r.setSpringForce(o),r.setNbodyForce(i),r.setDragForce(a),P(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(20);return N(),n>e},isNodePinned:function(e){var t=d(e.id);return t?m(t):void 0},pinNode:function(e,t){var n=d(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=d(e);return t||(g(e),t=d(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=d(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",b)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a={},u=function(e){e&&(a[e.id]||(a[e.id]=i(e)),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&u(n.node)}};return{run:function(){this.step()},step:function(){return s(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,d=!0,l=0,h=0,v=!1,p=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return v=u.step()&&!p,V(),!v},P=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(l=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},N=function(){v=!1,i.restart()},E=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),d=!1},L=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),p=!0,N()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),p=!0,V()},onStop:function(){u.pinNode(e,t),p=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),d&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(d=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},R=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);N()},D=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",R),o=null)},z=function(){x.on("resize",D),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){var r=Math.pow(1.4,0>t?-.2:.2);g.scale=s.scale(r,n),V(),w.fire("scale",g.scale)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",R)},B=function(){c=!1,O(),F(),x.stop("resize",D),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),E(),G(),C(),z(),c=!0),P(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},dispose:function(){B()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"}; +var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},d=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},l=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?d(e):(d=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,l()},translateRel:function(e,r){t+=e,n+=r,l()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,l()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),d=f.attr("id"),l=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&d===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&l===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i,o=1,a={},u={},s=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},f=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},c=function(){return Viva.Graph.svg("line").attr("stroke","#999")},d=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},l=function(e){e.fire("rescaled")},h={x:0,y:0},v={x:0,y:0},p={x:0,y:0},m=function(){if(e){var t="matrix("+o+", 0, 0,"+o+","+n+","+r+")";e.attr("transform",t)}},g={getNodeUI:function(e){return a[e]},getLinkUI:function(e){return u[e]},node:function(e){return"function"==typeof e?(s=e,this):void 0},link:function(e){return"function"==typeof e?(c=e,this):void 0},placeNode:function(e){return f=e,this},placeLink:function(e){return d=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,m()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(i,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(i).translate(-u.x,-u.y),f=e.getCTM().multiply(s);o=f.a,n=f.e,r=f.f;var c="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",c),l(this),o},resetScale:function(){o=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),l(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),m(),"function"==typeof i&&i(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(t,n){var r=c(t);if(r)return r.position=n,r.link=t,u[t.id]=r,e.childElementCount>0?e.insertBefore(r,e.firstChild):e.appendChild(r),r},releaseLink:function(t){var n=u[t.id];n&&(e.removeChild(n),delete u[t.id])},addNode:function(t,n){var r=s(t);if(r)return r.position=n,r.node=t,a[t.id]=r,e.appendChild(r),r},releaseNode:function(t){var n=a[t.id];n&&(e.removeChild(n),delete a[t.id])},renderNodes:function(){for(var e in a)if(a.hasOwnProperty(e)){var t=a[e];h.x=t.position.x,h.y=t.position.y,f(t,h,t.node)}},renderLinks:function(){for(var e in u)if(u.hasOwnProperty(e)){var t=u[e];v.x=t.position.from.x,v.y=t.position.from.y,p.x=t.position.to.x,p.y=t.position.to.y,d(t,v,p,t.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):i=e),t},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(g).extend(),g},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,d=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(d.x)+" "+Math.round(d.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),l=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),v=new Float32Array(h),p=new Uint32Array(h),m=0,g=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(p),v=t,p=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(l,d),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;v[n*f]=t.x,v[n*f+1]=t.y,v[n*f+2]=e.size,p[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(p,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,d=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),v=0,p=new ArrayBuffer(16*d),m=new Float32Array(p),g=new Uint32Array(p),y=function(){if((v+1)*d>p.byteLength){var e=new ArrayBuffer(2*p.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,p=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,l),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),v+=1,o=e.id},removeLink:function(e){v>0&&(v-=1),v>e.id&&v>0&&r.copyArrayPart(g,e.id*c,v*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,p,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*v),o=v-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},d=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},l=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},v=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},p=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=l(e),o={offset:e};r.textureNumber>=s.length&&d();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=l(t.offset),r=l(o);p(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],v(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){v(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,d=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),l=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,v=0,p=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(l,d),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;p[n]=t.x-e.size,p[n+1]=t.y-e.size,p[n+2]=4*e._offset,p[n+3]=t.x+e.size,p[n+4]=t.y-e.size,p[n+5]=4*e._offset+1,p[n+6]=t.x-e.size,p[n+7]=t.y+e.size,p[n+8]=4*e._offset+2,p[n+9]=t.x-e.size,p[n+10]=t.y+e.size,p[n+11]=4*e._offset+2,p[n+12]=t.x+e.size,p[n+13]=t.y-e.size,p[n+14]=4*e._offset+1,p[n+15]=t.x+e.size,p[n+16]=t.y+e.size,p[n+17]=4*e._offset+3},createNode:function(t){p=i.extendArray(p,v,c),v+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){v>0&&(v-=1),v>t.id&&v>0&&(t.src&&e.remove(t.src),i.copyArrayPart(p,t.id*c,v*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,p,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*v)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f,c=0,d=0,l=[],h=[],v={},p={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(a),g.updateTransform(a)},V=function(){a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},P=function(e){e.fire("rescaled")},N={getLinkUI:function(e){return p[e]},getNodeUI:function(e){return v[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return u=e,this},placeLink:function(e){return s=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){d>0&&m.render(),c>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(){b()},addLink:function(e,t){var n=d++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,p[e.id]=r,r},addNode:function(e,t){var n=c++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),l[n]=r,v[e.id]=r,r},translateRel:function(e,t){a[12]+=2*a[0]*e/i/a[0],a[13]-=2*a[5]*t/o/a[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=a[12],r-=a[13],a[12]+=n*(1-e),a[13]+=r*(1-e),a[0]*=e,a[5]*=e,w(),P(this),a[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var s="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(s),s}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof f&&f(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){d>0&&(d-=1);var t=p[e.id];delete p[e.id],m.removeLink(t);var n=t.id;if(d>n){if(0===d||d===n)return;var r=h[d];h[n]=r,r.id=n}},releaseNode:function(e){c>0&&(c-=1);var t=v[e.id];delete v[e.id],g.removeNode(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=l[c];l[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;c>t;++t){var n=l[t];e.x=n.position.x,e.y=-n.position.y,u&&u(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;d>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,s&&s(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):f=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-a[12])/a[0],e.y=(e.y-a[13])/a[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;c>n;++n)if(t(l[n],e.x,e.y))return l[n].node;return null}};return Viva.Graph.Utils.events(N).extend(),N},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},i=function(t){return e.getNodeAtClientPos(t,r)},o=null,a=[],u=[],s=[],f=[],c=[],d=[],l=[],h=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},p=function(e){return v(e),!1},m=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(e){var r={x:0,y:0},g=null,y=+new Date,x=function(e){m(c,[g,e]),r.x=e.clientX,r.y=e.clientY},w=function(){h.stop("mousemove",x),h.stop("mouseup",w)},V=function(){n=e.getBoundingClientRect()};window.addEventListener("resize",V),V(),e.addEventListener("mousemove",function(e){if(!o){var t,s=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,t=i(r),t&&g!==t?(g=t,s=s||m(a,[g])):null===t&&g!==t&&(s=s||m(u,[g]),g=null),s&&v(e)}}),e.addEventListener("mousedown",function(e){var o,a=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]?(a=m(s,o),h.on("mousemove",x),h.on("mouseup",w),t=window.document.onselectstart,window.document.onselectstart=p,g=o[0]):g=null,a&&v(e)}),e.addEventListener("mouseup",function(e){var o,a=+new Date;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]&&(window.document.onselectstart=t,400>a-y&&o[0]===g?m(l,o):m(d,o),y=a,m(f,o)&&v(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&l.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file diff --git a/src/Layout/forceDirected.js b/src/Layout/forceDirected.js index 0b66c4b..6afe7d6 100644 --- a/src/Layout/forceDirected.js +++ b/src/Layout/forceDirected.js @@ -64,6 +64,9 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { // TODO: Initial position could be picked better, e.g. take into // account all neighbouring nodes/links, not only one. // How about center of mass? + if (node.position) { + return node.position; + } var baseX = (graphRect.x1 + graphRect.x2) / 2, baseY = (graphRect.y1 + graphRect.y2) / 2, springLength = settings.springLength; From 9ce31408b024b20c8a09f326b7d2922fed7c000e Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 26 Oct 2013 01:36:03 -0700 Subject: [PATCH 041/276] Properly update graph rectangle when all nodes are removed --- dist/vivagraph.js | 4 ++++ dist/vivagraph.min.js | 2 +- src/Layout/forceDirected.js | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 8931168..3c69443 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -2227,6 +2227,10 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { releaseBody(node.id); forceSimulator.removeBody(body); + if (graph.getNodesCount() === 0) { + graphRect.x1 = graphRect.y1 = 0; + graphRect.x2 = graphRect.y2 = 0; + } } }, diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index e4f9564..6d4275b 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.0",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},P=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},N=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",P,!1):e.addEventListener("DOMMouseScroll",P,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",P,!1):e.removeEventListener("DOMMouseScroll",P,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),N(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,d=Math.sqrt(f*f+c*c);d>r&&(u.velocity.x=r*f/d,u.velocity.y=r*c/d),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};i="number"==typeof i?i:1;var o=new Viva.Graph.Physics.Spring(e,t,n,r>=0?r:-1,i);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),f={},c=function(e){if(e.position)return e.position;var n=(u.x1+u.x2)/2,r=(u.y1+u.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],a=o.fromId!==e.id?f[o.fromId]:f[o.toId];a&&a.location&&(n=a.location.x,r=a.location.y)}return{x:n+s.next(i)-i/2,y:r+s.next(i)-i/2}},d=function(e){return f[e]},l=function(e){f[e]=null,delete f[e]},h={},v=function(t){var n=d(t);n.mass=1+e.getLinks(t).length/3},p=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},m=function(e){return e.isPinned},g=function(t){var n=d(t);if(!n){var i=e.getNode(t);if(!i)return;n=new Viva.Graph.Physics.Body,f[t]=n;var o=c(i);n.loc(o),v(t),p(i)&&(n.isPinned=!0),r.addBody(n)}},y=function(e){g(e.id)},x=function(e){var t=d(e.id);t&&(l(e.id),r.removeBody(t))},w=function(e){v(e.fromId),v(e.toId);var t=d(e.fromId),n=d(e.toId),i=r.addSpring(t,n,-1,e.weight);h[e.id]=i},V=function(t){var n=h[t.id];if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&v(i.id),o&&v(o.id),delete h[t.id],r.removeSpring(n)}},b=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&g(n.node.id),n.link&&w(n.link)):"remove"===n.changeType&&(n.node&&x(n.node),n.link&&V(n.link))}},P=function(){e.forEachNode(y),e.forEachLink(w),e.addEventListener("changed",b)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in f)if(f.hasOwnProperty(o)){var a=f[o];m(a)?(a.location.x=a.prevLocation.x,a.location.y=a.prevLocation.y):(a.prevLocation.x=a.location.x,a.prevLocation.y=a.location.y),t>a.location.x&&(t=a.location.x),a.location.x>r&&(r=a.location.x),n>a.location.y&&(n=a.location.y),a.location.y>i&&(i=a.location.y)}u.x1=t,u.x2=r,u.y1=n,u.y2=i}};return r.setSpringForce(o),r.setNbodyForce(i),r.setDragForce(a),P(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(20);return N(),n>e},isNodePinned:function(e){var t=d(e.id);return t?m(t):void 0},pinNode:function(e,t){var n=d(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=d(e);return t||(g(e),t=d(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=d(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",b)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a={},u=function(e){e&&(a[e.id]||(a[e.id]=i(e)),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&u(n.node)}};return{run:function(){this.step()},step:function(){return s(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,d=!0,l=0,h=0,v=!1,p=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return v=u.step()&&!p,V(),!v},P=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(l=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},N=function(){v=!1,i.restart()},E=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),d=!1},L=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),p=!0,N()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),p=!0,V()},onStop:function(){u.pinNode(e,t),p=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),d&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(d=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},R=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);N()},D=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",R),o=null)},z=function(){x.on("resize",D),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){var r=Math.pow(1.4,0>t?-.2:.2);g.scale=s.scale(r,n),V(),w.fire("scale",g.scale)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",R)},B=function(){c=!1,O(),F(),x.stop("resize",D),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),E(),G(),C(),z(),c=!0),P(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},dispose:function(){B()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"}; +var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.0",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},P=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},N=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",P,!1):e.addEventListener("DOMMouseScroll",P,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",P,!1):e.removeEventListener("DOMMouseScroll",P,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),N(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,d=Math.sqrt(f*f+c*c);d>r&&(u.velocity.x=r*f/d,u.velocity.y=r*c/d),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};i="number"==typeof i?i:1;var o=new Viva.Graph.Physics.Spring(e,t,n,r>=0?r:-1,i);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),f={},c=function(e){if(e.position)return e.position;var n=(u.x1+u.x2)/2,r=(u.y1+u.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],a=o.fromId!==e.id?f[o.fromId]:f[o.toId];a&&a.location&&(n=a.location.x,r=a.location.y)}return{x:n+s.next(i)-i/2,y:r+s.next(i)-i/2}},d=function(e){return f[e]},l=function(e){f[e]=null,delete f[e]},h={},v=function(t){var n=d(t);n.mass=1+e.getLinks(t).length/3},p=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},m=function(e){return e.isPinned},g=function(t){var n=d(t);if(!n){var i=e.getNode(t);if(!i)return;n=new Viva.Graph.Physics.Body,f[t]=n;var o=c(i);n.loc(o),v(t),p(i)&&(n.isPinned=!0),r.addBody(n)}},y=function(e){g(e.id)},x=function(t){var n=d(t.id);n&&(l(t.id),r.removeBody(n),0===e.getNodesCount()&&(u.x1=u.y1=0,u.x2=u.y2=0))},w=function(e){v(e.fromId),v(e.toId);var t=d(e.fromId),n=d(e.toId),i=r.addSpring(t,n,-1,e.weight);h[e.id]=i},V=function(t){var n=h[t.id];if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&v(i.id),o&&v(o.id),delete h[t.id],r.removeSpring(n)}},b=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&g(n.node.id),n.link&&w(n.link)):"remove"===n.changeType&&(n.node&&x(n.node),n.link&&V(n.link))}},P=function(){e.forEachNode(y),e.forEachLink(w),e.addEventListener("changed",b)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in f)if(f.hasOwnProperty(o)){var a=f[o];m(a)?(a.location.x=a.prevLocation.x,a.location.y=a.prevLocation.y):(a.prevLocation.x=a.location.x,a.prevLocation.y=a.location.y),t>a.location.x&&(t=a.location.x),a.location.x>r&&(r=a.location.x),n>a.location.y&&(n=a.location.y),a.location.y>i&&(i=a.location.y)}u.x1=t,u.x2=r,u.y1=n,u.y2=i}};return r.setSpringForce(o),r.setNbodyForce(i),r.setDragForce(a),P(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(20);return N(),n>e},isNodePinned:function(e){var t=d(e.id);return t?m(t):void 0},pinNode:function(e,t){var n=d(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=d(e);return t||(g(e),t=d(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=d(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",b)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a={},u=function(e){e&&(a[e.id]||(a[e.id]=i(e)),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&u(n.node)}};return{run:function(){this.step()},step:function(){return s(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,d=!0,l=0,h=0,v=!1,p=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return v=u.step()&&!p,V(),!v},P=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(l=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},N=function(){v=!1,i.restart()},E=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),d=!1},L=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),p=!0,N()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),p=!0,V()},onStop:function(){u.pinNode(e,t),p=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),d&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(d=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},R=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);N()},D=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",R),o=null)},z=function(){x.on("resize",D),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){var r=Math.pow(1.4,0>t?-.2:.2);g.scale=s.scale(r,n),V(),w.fire("scale",g.scale)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",R)},B=function(){c=!1,O(),F(),x.stop("resize",D),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),E(),G(),C(),z(),c=!0),P(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},dispose:function(){B()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"}; var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},d=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},l=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?d(e):(d=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,l()},translateRel:function(e,r){t+=e,n+=r,l()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,l()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),d=f.attr("id"),l=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&d===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&l===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i,o=1,a={},u={},s=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},f=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},c=function(){return Viva.Graph.svg("line").attr("stroke","#999")},d=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},l=function(e){e.fire("rescaled")},h={x:0,y:0},v={x:0,y:0},p={x:0,y:0},m=function(){if(e){var t="matrix("+o+", 0, 0,"+o+","+n+","+r+")";e.attr("transform",t)}},g={getNodeUI:function(e){return a[e]},getLinkUI:function(e){return u[e]},node:function(e){return"function"==typeof e?(s=e,this):void 0},link:function(e){return"function"==typeof e?(c=e,this):void 0},placeNode:function(e){return f=e,this},placeLink:function(e){return d=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,m()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(i,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(i).translate(-u.x,-u.y),f=e.getCTM().multiply(s);o=f.a,n=f.e,r=f.f;var c="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",c),l(this),o},resetScale:function(){o=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),l(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),m(),"function"==typeof i&&i(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(t,n){var r=c(t);if(r)return r.position=n,r.link=t,u[t.id]=r,e.childElementCount>0?e.insertBefore(r,e.firstChild):e.appendChild(r),r},releaseLink:function(t){var n=u[t.id];n&&(e.removeChild(n),delete u[t.id])},addNode:function(t,n){var r=s(t);if(r)return r.position=n,r.node=t,a[t.id]=r,e.appendChild(r),r},releaseNode:function(t){var n=a[t.id];n&&(e.removeChild(n),delete a[t.id])},renderNodes:function(){for(var e in a)if(a.hasOwnProperty(e)){var t=a[e];h.x=t.position.x,h.y=t.position.y,f(t,h,t.node)}},renderLinks:function(){for(var e in u)if(u.hasOwnProperty(e)){var t=u[e];v.x=t.position.from.x,v.y=t.position.from.y,p.x=t.position.to.x,p.y=t.position.to.y,d(t,v,p,t.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):i=e),t},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(g).extend(),g},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,d=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(d.x)+" "+Math.round(d.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),l=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),v=new Float32Array(h),p=new Uint32Array(h),m=0,g=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(p),v=t,p=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(l,d),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;v[n*f]=t.x,v[n*f+1]=t.y,v[n*f+2]=e.size,p[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(p,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,d=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),v=0,p=new ArrayBuffer(16*d),m=new Float32Array(p),g=new Uint32Array(p),y=function(){if((v+1)*d>p.byteLength){var e=new ArrayBuffer(2*p.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,p=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,l),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),v+=1,o=e.id},removeLink:function(e){v>0&&(v-=1),v>e.id&&v>0&&r.copyArrayPart(g,e.id*c,v*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,p,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*v),o=v-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},d=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},l=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},v=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},p=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=l(e),o={offset:e};r.textureNumber>=s.length&&d();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=l(t.offset),r=l(o);p(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],v(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){v(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,d=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),l=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,v=0,p=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(l,d),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;p[n]=t.x-e.size,p[n+1]=t.y-e.size,p[n+2]=4*e._offset,p[n+3]=t.x+e.size,p[n+4]=t.y-e.size,p[n+5]=4*e._offset+1,p[n+6]=t.x-e.size,p[n+7]=t.y+e.size,p[n+8]=4*e._offset+2,p[n+9]=t.x-e.size,p[n+10]=t.y+e.size,p[n+11]=4*e._offset+2,p[n+12]=t.x+e.size,p[n+13]=t.y-e.size,p[n+14]=4*e._offset+1,p[n+15]=t.x+e.size,p[n+16]=t.y+e.size,p[n+17]=4*e._offset+3},createNode:function(t){p=i.extendArray(p,v,c),v+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){v>0&&(v-=1),v>t.id&&v>0&&(t.src&&e.remove(t.src),i.copyArrayPart(p,t.id*c,v*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,p,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*v)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f,c=0,d=0,l=[],h=[],v={},p={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(a),g.updateTransform(a)},V=function(){a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},P=function(e){e.fire("rescaled")},N={getLinkUI:function(e){return p[e]},getNodeUI:function(e){return v[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return u=e,this},placeLink:function(e){return s=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){d>0&&m.render(),c>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(){b()},addLink:function(e,t){var n=d++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,p[e.id]=r,r},addNode:function(e,t){var n=c++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),l[n]=r,v[e.id]=r,r},translateRel:function(e,t){a[12]+=2*a[0]*e/i/a[0],a[13]-=2*a[5]*t/o/a[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=a[12],r-=a[13],a[12]+=n*(1-e),a[13]+=r*(1-e),a[0]*=e,a[5]*=e,w(),P(this),a[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var s="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(s),s}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof f&&f(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){d>0&&(d-=1);var t=p[e.id];delete p[e.id],m.removeLink(t);var n=t.id;if(d>n){if(0===d||d===n)return;var r=h[d];h[n]=r,r.id=n}},releaseNode:function(e){c>0&&(c-=1);var t=v[e.id];delete v[e.id],g.removeNode(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=l[c];l[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;c>t;++t){var n=l[t];e.x=n.position.x,e.y=-n.position.y,u&&u(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;d>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,s&&s(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):f=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-a[12])/a[0],e.y=(e.y-a[13])/a[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;c>n;++n)if(t(l[n],e.x,e.y))return l[n].node;return null}};return Viva.Graph.Utils.events(N).extend(),N},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},i=function(t){return e.getNodeAtClientPos(t,r)},o=null,a=[],u=[],s=[],f=[],c=[],d=[],l=[],h=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},p=function(e){return v(e),!1},m=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(e){var r={x:0,y:0},g=null,y=+new Date,x=function(e){m(c,[g,e]),r.x=e.clientX,r.y=e.clientY},w=function(){h.stop("mousemove",x),h.stop("mouseup",w)},V=function(){n=e.getBoundingClientRect()};window.addEventListener("resize",V),V(),e.addEventListener("mousemove",function(e){if(!o){var t,s=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,t=i(r),t&&g!==t?(g=t,s=s||m(a,[g])):null===t&&g!==t&&(s=s||m(u,[g]),g=null),s&&v(e)}}),e.addEventListener("mousedown",function(e){var o,a=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]?(a=m(s,o),h.on("mousemove",x),h.on("mouseup",w),t=window.document.onselectstart,window.document.onselectstart=p,g=o[0]):g=null,a&&v(e)}),e.addEventListener("mouseup",function(e){var o,a=+new Date;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]&&(window.document.onselectstart=t,400>a-y&&o[0]===g?m(l,o):m(d,o),y=a,m(f,o)&&v(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&l.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file diff --git a/src/Layout/forceDirected.js b/src/Layout/forceDirected.js index 6afe7d6..bdbe66d 100644 --- a/src/Layout/forceDirected.js +++ b/src/Layout/forceDirected.js @@ -141,6 +141,10 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { releaseBody(node.id); forceSimulator.removeBody(body); + if (graph.getNodesCount() === 0) { + graphRect.x1 = graphRect.y1 = 0; + graphRect.x2 = graphRect.y2 = 0; + } } }, From 0ded379648f7e9d7d605535a9c0ab294c210d93f Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 20 Nov 2013 21:12:05 -0800 Subject: [PATCH 042/276] Fixed wrong arguments order --- dist/vivagraph.js | 2 +- dist/vivagraph.min.js | 2 +- src/Physics/forceSimulator.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 3c69443..efc0c8e 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -2018,7 +2018,7 @@ Viva.Graph.Physics.forceSimulator = function (forceIntegrator) { /** * Adds a spring to this simulation. */ - addSpring: function (body1, body2, springLength, springCoefficient, springWeight) { + addSpring: function (body1, body2, springLength, springWeight, springCoefficient) { if (!body1 || !body2) { throw { message : 'Cannot add null spring to force simulator' diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 6d4275b..3abe7a6 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.0",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},P=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},N=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",P,!1):e.addEventListener("DOMMouseScroll",P,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",P,!1):e.removeEventListener("DOMMouseScroll",P,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),N(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,d=Math.sqrt(f*f+c*c);d>r&&(u.velocity.x=r*f/d,u.velocity.y=r*c/d),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};i="number"==typeof i?i:1;var o=new Viva.Graph.Physics.Spring(e,t,n,r>=0?r:-1,i);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),f={},c=function(e){if(e.position)return e.position;var n=(u.x1+u.x2)/2,r=(u.y1+u.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],a=o.fromId!==e.id?f[o.fromId]:f[o.toId];a&&a.location&&(n=a.location.x,r=a.location.y)}return{x:n+s.next(i)-i/2,y:r+s.next(i)-i/2}},d=function(e){return f[e]},l=function(e){f[e]=null,delete f[e]},h={},v=function(t){var n=d(t);n.mass=1+e.getLinks(t).length/3},p=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},m=function(e){return e.isPinned},g=function(t){var n=d(t);if(!n){var i=e.getNode(t);if(!i)return;n=new Viva.Graph.Physics.Body,f[t]=n;var o=c(i);n.loc(o),v(t),p(i)&&(n.isPinned=!0),r.addBody(n)}},y=function(e){g(e.id)},x=function(t){var n=d(t.id);n&&(l(t.id),r.removeBody(n),0===e.getNodesCount()&&(u.x1=u.y1=0,u.x2=u.y2=0))},w=function(e){v(e.fromId),v(e.toId);var t=d(e.fromId),n=d(e.toId),i=r.addSpring(t,n,-1,e.weight);h[e.id]=i},V=function(t){var n=h[t.id];if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&v(i.id),o&&v(o.id),delete h[t.id],r.removeSpring(n)}},b=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&g(n.node.id),n.link&&w(n.link)):"remove"===n.changeType&&(n.node&&x(n.node),n.link&&V(n.link))}},P=function(){e.forEachNode(y),e.forEachLink(w),e.addEventListener("changed",b)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in f)if(f.hasOwnProperty(o)){var a=f[o];m(a)?(a.location.x=a.prevLocation.x,a.location.y=a.prevLocation.y):(a.prevLocation.x=a.location.x,a.prevLocation.y=a.location.y),t>a.location.x&&(t=a.location.x),a.location.x>r&&(r=a.location.x),n>a.location.y&&(n=a.location.y),a.location.y>i&&(i=a.location.y)}u.x1=t,u.x2=r,u.y1=n,u.y2=i}};return r.setSpringForce(o),r.setNbodyForce(i),r.setDragForce(a),P(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(20);return N(),n>e},isNodePinned:function(e){var t=d(e.id);return t?m(t):void 0},pinNode:function(e,t){var n=d(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=d(e);return t||(g(e),t=d(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=d(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",b)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a={},u=function(e){e&&(a[e.id]||(a[e.id]=i(e)),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&u(n.node)}};return{run:function(){this.step()},step:function(){return s(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,d=!0,l=0,h=0,v=!1,p=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return v=u.step()&&!p,V(),!v},P=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(l=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},N=function(){v=!1,i.restart()},E=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),d=!1},L=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),p=!0,N()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),p=!0,V()},onStop:function(){u.pinNode(e,t),p=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),d&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(d=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},R=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);N()},D=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",R),o=null)},z=function(){x.on("resize",D),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){var r=Math.pow(1.4,0>t?-.2:.2);g.scale=s.scale(r,n),V(),w.fire("scale",g.scale)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",R)},B=function(){c=!1,O(),F(),x.stop("resize",D),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),E(),G(),C(),z(),c=!0),P(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},dispose:function(){B()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"}; +var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.0",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},P=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},N=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",P,!1):e.addEventListener("DOMMouseScroll",P,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",P,!1):e.removeEventListener("DOMMouseScroll",P,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),N(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,d=Math.sqrt(f*f+c*c);d>r&&(u.velocity.x=r*f/d,u.velocity.y=r*c/d),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};r="number"==typeof r?r:1;var o=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,r);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),f={},c=function(e){if(e.position)return e.position;var n=(u.x1+u.x2)/2,r=(u.y1+u.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],a=o.fromId!==e.id?f[o.fromId]:f[o.toId];a&&a.location&&(n=a.location.x,r=a.location.y)}return{x:n+s.next(i)-i/2,y:r+s.next(i)-i/2}},d=function(e){return f[e]},l=function(e){f[e]=null,delete f[e]},h={},v=function(t){var n=d(t);n.mass=1+e.getLinks(t).length/3},p=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},m=function(e){return e.isPinned},g=function(t){var n=d(t);if(!n){var i=e.getNode(t);if(!i)return;n=new Viva.Graph.Physics.Body,f[t]=n;var o=c(i);n.loc(o),v(t),p(i)&&(n.isPinned=!0),r.addBody(n)}},y=function(e){g(e.id)},x=function(t){var n=d(t.id);n&&(l(t.id),r.removeBody(n),0===e.getNodesCount()&&(u.x1=u.y1=0,u.x2=u.y2=0))},w=function(e){v(e.fromId),v(e.toId);var t=d(e.fromId),n=d(e.toId),i=r.addSpring(t,n,-1,e.weight);h[e.id]=i},V=function(t){var n=h[t.id];if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&v(i.id),o&&v(o.id),delete h[t.id],r.removeSpring(n)}},b=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&g(n.node.id),n.link&&w(n.link)):"remove"===n.changeType&&(n.node&&x(n.node),n.link&&V(n.link))}},P=function(){e.forEachNode(y),e.forEachLink(w),e.addEventListener("changed",b)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in f)if(f.hasOwnProperty(o)){var a=f[o];m(a)?(a.location.x=a.prevLocation.x,a.location.y=a.prevLocation.y):(a.prevLocation.x=a.location.x,a.prevLocation.y=a.location.y),t>a.location.x&&(t=a.location.x),a.location.x>r&&(r=a.location.x),n>a.location.y&&(n=a.location.y),a.location.y>i&&(i=a.location.y)}u.x1=t,u.x2=r,u.y1=n,u.y2=i}};return r.setSpringForce(o),r.setNbodyForce(i),r.setDragForce(a),P(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(20);return N(),n>e},isNodePinned:function(e){var t=d(e.id);return t?m(t):void 0},pinNode:function(e,t){var n=d(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=d(e);return t||(g(e),t=d(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=d(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",b)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a={},u=function(e){e&&(a[e.id]||(a[e.id]=i(e)),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&u(n.node)}};return{run:function(){this.step()},step:function(){return s(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,d=!0,l=0,h=0,v=!1,p=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return v=u.step()&&!p,V(),!v},P=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(l=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},N=function(){v=!1,i.restart()},E=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),d=!1},L=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),p=!0,N()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),p=!0,V()},onStop:function(){u.pinNode(e,t),p=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),d&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(d=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},R=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);N()},D=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",R),o=null)},z=function(){x.on("resize",D),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){var r=Math.pow(1.4,0>t?-.2:.2);g.scale=s.scale(r,n),V(),w.fire("scale",g.scale)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",R)},B=function(){c=!1,O(),F(),x.stop("resize",D),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),E(),G(),C(),z(),c=!0),P(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},dispose:function(){B()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"}; var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},d=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},l=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?d(e):(d=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,l()},translateRel:function(e,r){t+=e,n+=r,l()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,l()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),d=f.attr("id"),l=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&d===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&l===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i,o=1,a={},u={},s=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},f=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},c=function(){return Viva.Graph.svg("line").attr("stroke","#999")},d=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},l=function(e){e.fire("rescaled")},h={x:0,y:0},v={x:0,y:0},p={x:0,y:0},m=function(){if(e){var t="matrix("+o+", 0, 0,"+o+","+n+","+r+")";e.attr("transform",t)}},g={getNodeUI:function(e){return a[e]},getLinkUI:function(e){return u[e]},node:function(e){return"function"==typeof e?(s=e,this):void 0},link:function(e){return"function"==typeof e?(c=e,this):void 0},placeNode:function(e){return f=e,this},placeLink:function(e){return d=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,m()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(i,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(i).translate(-u.x,-u.y),f=e.getCTM().multiply(s);o=f.a,n=f.e,r=f.f;var c="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",c),l(this),o},resetScale:function(){o=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),l(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),m(),"function"==typeof i&&i(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(t,n){var r=c(t);if(r)return r.position=n,r.link=t,u[t.id]=r,e.childElementCount>0?e.insertBefore(r,e.firstChild):e.appendChild(r),r},releaseLink:function(t){var n=u[t.id];n&&(e.removeChild(n),delete u[t.id])},addNode:function(t,n){var r=s(t);if(r)return r.position=n,r.node=t,a[t.id]=r,e.appendChild(r),r},releaseNode:function(t){var n=a[t.id];n&&(e.removeChild(n),delete a[t.id])},renderNodes:function(){for(var e in a)if(a.hasOwnProperty(e)){var t=a[e];h.x=t.position.x,h.y=t.position.y,f(t,h,t.node)}},renderLinks:function(){for(var e in u)if(u.hasOwnProperty(e)){var t=u[e];v.x=t.position.from.x,v.y=t.position.from.y,p.x=t.position.to.x,p.y=t.position.to.y,d(t,v,p,t.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):i=e),t},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(g).extend(),g},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,d=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(d.x)+" "+Math.round(d.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),l=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),v=new Float32Array(h),p=new Uint32Array(h),m=0,g=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(p),v=t,p=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(l,d),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;v[n*f]=t.x,v[n*f+1]=t.y,v[n*f+2]=e.size,p[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(p,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,d=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),v=0,p=new ArrayBuffer(16*d),m=new Float32Array(p),g=new Uint32Array(p),y=function(){if((v+1)*d>p.byteLength){var e=new ArrayBuffer(2*p.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,p=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,l),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),v+=1,o=e.id},removeLink:function(e){v>0&&(v-=1),v>e.id&&v>0&&r.copyArrayPart(g,e.id*c,v*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,p,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*v),o=v-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},d=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},l=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},v=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},p=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=l(e),o={offset:e};r.textureNumber>=s.length&&d();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=l(t.offset),r=l(o);p(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],v(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){v(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,d=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),l=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,v=0,p=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(l,d),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;p[n]=t.x-e.size,p[n+1]=t.y-e.size,p[n+2]=4*e._offset,p[n+3]=t.x+e.size,p[n+4]=t.y-e.size,p[n+5]=4*e._offset+1,p[n+6]=t.x-e.size,p[n+7]=t.y+e.size,p[n+8]=4*e._offset+2,p[n+9]=t.x-e.size,p[n+10]=t.y+e.size,p[n+11]=4*e._offset+2,p[n+12]=t.x+e.size,p[n+13]=t.y-e.size,p[n+14]=4*e._offset+1,p[n+15]=t.x+e.size,p[n+16]=t.y+e.size,p[n+17]=4*e._offset+3},createNode:function(t){p=i.extendArray(p,v,c),v+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){v>0&&(v-=1),v>t.id&&v>0&&(t.src&&e.remove(t.src),i.copyArrayPart(p,t.id*c,v*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,p,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*v)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f,c=0,d=0,l=[],h=[],v={},p={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(a),g.updateTransform(a)},V=function(){a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},P=function(e){e.fire("rescaled")},N={getLinkUI:function(e){return p[e]},getNodeUI:function(e){return v[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return u=e,this},placeLink:function(e){return s=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){d>0&&m.render(),c>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(){b()},addLink:function(e,t){var n=d++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,p[e.id]=r,r},addNode:function(e,t){var n=c++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),l[n]=r,v[e.id]=r,r},translateRel:function(e,t){a[12]+=2*a[0]*e/i/a[0],a[13]-=2*a[5]*t/o/a[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=a[12],r-=a[13],a[12]+=n*(1-e),a[13]+=r*(1-e),a[0]*=e,a[5]*=e,w(),P(this),a[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var s="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(s),s}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof f&&f(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){d>0&&(d-=1);var t=p[e.id];delete p[e.id],m.removeLink(t);var n=t.id;if(d>n){if(0===d||d===n)return;var r=h[d];h[n]=r,r.id=n}},releaseNode:function(e){c>0&&(c-=1);var t=v[e.id];delete v[e.id],g.removeNode(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=l[c];l[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;c>t;++t){var n=l[t];e.x=n.position.x,e.y=-n.position.y,u&&u(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;d>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,s&&s(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):f=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-a[12])/a[0],e.y=(e.y-a[13])/a[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;c>n;++n)if(t(l[n],e.x,e.y))return l[n].node;return null}};return Viva.Graph.Utils.events(N).extend(),N},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},i=function(t){return e.getNodeAtClientPos(t,r)},o=null,a=[],u=[],s=[],f=[],c=[],d=[],l=[],h=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},p=function(e){return v(e),!1},m=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(e){var r={x:0,y:0},g=null,y=+new Date,x=function(e){m(c,[g,e]),r.x=e.clientX,r.y=e.clientY},w=function(){h.stop("mousemove",x),h.stop("mouseup",w)},V=function(){n=e.getBoundingClientRect()};window.addEventListener("resize",V),V(),e.addEventListener("mousemove",function(e){if(!o){var t,s=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,t=i(r),t&&g!==t?(g=t,s=s||m(a,[g])):null===t&&g!==t&&(s=s||m(u,[g]),g=null),s&&v(e)}}),e.addEventListener("mousedown",function(e){var o,a=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]?(a=m(s,o),h.on("mousemove",x),h.on("mouseup",w),t=window.document.onselectstart,window.document.onselectstart=p,g=o[0]):g=null,a&&v(e)}),e.addEventListener("mouseup",function(e){var o,a=+new Date;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]&&(window.document.onselectstart=t,400>a-y&&o[0]===g?m(l,o):m(d,o),y=a,m(f,o)&&v(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&l.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file diff --git a/src/Physics/forceSimulator.js b/src/Physics/forceSimulator.js index 0cea585..8cf6ee5 100644 --- a/src/Physics/forceSimulator.js +++ b/src/Physics/forceSimulator.js @@ -94,7 +94,7 @@ Viva.Graph.Physics.forceSimulator = function (forceIntegrator) { /** * Adds a spring to this simulation. */ - addSpring: function (body1, body2, springLength, springCoefficient, springWeight) { + addSpring: function (body1, body2, springLength, springWeight, springCoefficient) { if (!body1 || !body2) { throw { message : 'Cannot add null spring to force simulator' From 88914b2f366f6e6d256f7ebc49ad66eca90a02f4 Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 20 Nov 2013 21:12:33 -0800 Subject: [PATCH 043/276] Don't need that whitespace --- unit_tests/testRunner.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/unit_tests/testRunner.html b/unit_tests/testRunner.html index e40a6aa..50ebc76 100644 --- a/unit_tests/testRunner.html +++ b/unit_tests/testRunner.html @@ -6,7 +6,7 @@ VivaGraphs test page - + @@ -14,16 +14,16 @@ - + + + + Each link has custom length + + diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 53a3b8f..8e52f46 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -7,7 +7,7 @@ Viva.Graph = Viva.Graph || {}; if (typeof module !== 'undefined' && module.exports) { module.exports = Viva; } -Viva.Graph.version = '0.4.1'; +Viva.Graph.version = '0.4.2'; /** * Extends target object with given fields/values in the options object. * Unlike jQuery's extend this method does not override target object @@ -2266,7 +2266,37 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { * Drag force coefficient. Used to slow down system, thus should be less than 1. * The closer it is to 0 the less tight system will be. */ - dragCoeff: 0.02 + dragCoeff: 0.02, + + /** + * Allows to transfor physical spring associated with a link. this allows clients + * to specify custom length for a link. + * + * @param {Viva.Graph.Link} link actual link for which transform is performed + * @param {Viva.Graph.Physics.Spring} spring physical spring which is associated with + * a link. Most interesting property will be 'length' + * + * @example + * // Let's say your graph represent friendship. Each link has associated + * // 'strength' of connection, distributed from 0 (not a strong connection) to + * // 1 (very strong connection) + * // + * // You want your graph to have uniformly distributed links, but stronger + * // connection should pull nodes closer: + * + * graph.addLink(user1, user2, { friendshipStrength: 0.9 }); + * var layout = Viva.Graph.Layout.forceDirected(graph, { + * springLength: 80, // 80 pixels is our ideal link length + * springTransform: function (link, spring) { + * // We can set custom desired length of a spring, based on + * // link's data: + * spring.length = 80 * (1 - link.data.friendshipStrength); + * } + * } + */ + springTransform: function (link, spring) { + // By default, it is a no-op + } }); var forceSimulator = Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()), @@ -2346,6 +2376,7 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { updateNodeMass(from); updateNodeMass(to); link.force_directed_spring = forceSimulator.addSpring(from.force_directed_body, to.force_directed_body, -1.0, link.weight); + settings.springTransform(link, link.force_directed_spring); }, releaseLink = function(link) { diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 9b6027a..dfc1541 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.4.1",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){function e(){var e=4022871197,t=function(t){var n;for(t=""+t,n=0;t.length>n;n++){e+=t.charCodeAt(n);var r=.02519603282416938*e;e=r>>>0,r-=e,r*=e,e=r>>>0,r-=e,e+=4294967296*r}return 2.3283064365386963e-10*(e>>>0)};return t.version="Mash 0.9",t}function t(t){return function(t){var n,r,i=0,o=58,a=119,u=178,s=[],c=e();for(0===t.length&&(t=[+new Date]),n=0;256>n;n++)s[n]=c(" "),s[n]-=4.76837158203125e-7*c(" "),0>s[n]&&(s[n]+=1);for(r=0;t.length>r;r++)for(n=0;256>n;n++)s[n]-=c(t[r]),s[n]-=4.76837158203125e-7*c(t[r]),0>s[n]&&(s[n]+=1);c=null;var f=function(){var e;return i=255&i+1,o=255&o+1,a=255&a+1,u=255&u+1,e=s[i]-s[o],0>e&&(e+=1),e-=s[a],0>e&&(e+=1),e-=s[u],0>e&&(e+=1),s[i]=e,e};return f.uint32=function(){return 4294967296*f()>>>0},f.fract53=f,f.version="LFIB4 0.9",f.args=t,f}(t)}var n=new t(Array.prototype.slice.call(arguments));return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),c=Viva.Graph.Utils.events(e),f=Viva.Graph.Utils.findElementPosition,l=0,d=0,h=!1,p=0,v=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-l,y:r-d}),l=t,d=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(l=e.clientX,d=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:l,y:d}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},E=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=v(t),o=f(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},G=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",E,!1):e.addEventListener("DOMMouseScroll",E,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",E,!1):e.removeEventListener("DOMMouseScroll",E,!1)),i=t},P=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},N=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=P(e.touches[0],e.touches[1]),r=0;p>n?r=-1:n>p&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),p=n,g(e),y(e)}},_=function(e){h=!1,s.stop("touchmove",N),s.stop("touchend",_),s.stop("touchcancel",_),u=null,r&&r(e)},L=function(e,n){g(e),y(e),l=n.clientX,d=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:l,y:d}),h||(h=!0,s.on("touchmove",N),s.on("touchend",_),s.on("touchcancel",_))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?L(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),p=P(t.touches[0],t.touches[1])),void 0)};return c.on("mousedown",V),c.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return G(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",N),s.stop("touchend",_),s.stop("touchcancel",_),G(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(){return{bindDragNDrop:function(e,t){if(t){var n=Viva.Graph.Utils.dragndrop(e.ui);"function"==typeof t.onStart&&n.onStart(t.onStart),"function"==typeof t.onDrag&&n.onDrag(t.onDrag),"function"==typeof t.onStop&&n.onStop(t.onStop),e.events=n}else e.events&&(e.events.release(),e.events=null,delete e.events)}}},Viva.Graph.spatialIndex=function(e,t){var n,r,i=16;return"function"==typeof t?(r=t,n=function(t,n){var i=null;return e.forEachNode(function(e){return r(e,t,n)?(i=e,!0):void 0}),i}):"number"==typeof t&&(i=t,n=function(t,n){var r=null;return e.forEachNode(function(e){var o=e.position;return t>o.x-i&&o.x+i>t&&n>o.y-i&&o.y+i>n?(r=e,!0):void 0}),r}),{getNodeAt:n}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,c,f,l,d,h,p,v,m,g,y,x,w,V={x:0,y:0};return s=r-t,f=e-n,d=n*t-e*r,m=s*i+f*o+d,g=s*a+f*u+d,0!==m&&0!==g&&m>=0==g>=4?null:(c=u-o,l=i-a,h=a*o-i*u,p=c*e+l*t+h,v=c*n+l*r+h,0!==p&&0!==v&&p>=0==v>=0?null:(y=s*l-c*f,0===y?null:(x=0>y?-y/2:y/2,x=0,w=f*h-l*d,V.x=(0>w?w-x:w+x)/y,w=c*d-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,c=a.y-e.y,f=s*s+c*c;for(r=1;o.length>r;++r){a=o[r];var l=i(a);l===u?(s=a.x-e.x,c=a.y-e.y,n=s*s+c*c,f>n?o.splice(r,1):o.splice(r-1,1)):u=l}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n){this.fromId=e,this.toId=t,this.data=n},Viva.Graph.graph=function(){var e={},t=[],n=0,r=0,i=[],o=function(e){e.fire("changed",i)},a=function(){r+=1},u=function(e){r-=1,0===r&&i.length>0&&(o(e),i.length=0)},s=function(e,t){i.push({node:e,changeType:t})},c=function(e,t){i.push({link:e,changeType:t})},f=function(e){return e&&"object"==typeof e&&"number"==typeof e.length&&"function"==typeof e.splice&&!e.propertyIsEnumerable("length")},l={addNode:function(t,r){if(t===void 0)throw{message:"Invalid node identifier"};a();var i=this.getNode(t);if(i?s(i,"update"):(i=new Viva.Graph.Node(t),n++,s(i,"add")),r){var o,c=i.data||{},l=typeof r;if("string"===l||f(r)||"number"===l||"boolean"===l)c=r;else if("undefined"===l)c=null;else for(o in r)r.hasOwnProperty(o)&&(c[o]=r[o]);i.data=c}return e[t]=i,u(this),i},addLink:function(e,n,r){a();var i=this.getNode(e)||this.addNode(e),o=this.getNode(n)||this.addNode(n),s=new Viva.Graph.Link(e,n,r);return t.push(s),i.links.push(s),o.links.push(s),c(s,"add"),u(this),s},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;a(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),u(this),!0},removeNode:function(t){var r=this.getNode(t);if(!r)return!1;for(a();r.links.length;){var i=r.links[0];this.removeLink(i)}e[t]=null,delete e[t],n--,s(r,"remove"),u(this)},getNode:function(t){return e[t]},getNodesCount:function(){return n},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n;if("function"==typeof e)for(n=0;t.length>n;++n)e(t[n])},beginUpdate:function(){a()},endUpdate:function(){u(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(l).extend(),l},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var c=u.velocity.x,f=u.velocity.y,l=Math.sqrt(c*c+f*f);l>r&&(u.velocity.x=r*c/l,u.velocity.y=r*f/l),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},c=[],f=0,l=function(){var e;return c[f]?(e=c[f],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,c[f]=e),++f,e},d=l(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return.01>n&&.01>r},p=function(e){for(o.reset(),o.push(d,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,c=n.left,f=(n.right+c)/2,p=n.top,v=(n.bottom+p)/2;if(i>f){s+=1;var m=c;c=f,f+=f-m}if(a>v){s+=2;var g=p;p=v,v+=v-g}var y=n.quads[s];y||(y=l(),y.left=c,y.top=p,y.right=f,y.bottom=v,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){var w,V;do{var b=2*u.nextDouble()*Math.PI,E=.006*(n.right-n.left)*Math.cos(b),G=.006*(n.bottom-n.top)*Math.sin(b);w=x.location.x+E,V=x.location.y+G}while(n.left>w||w>n.right||n.top>V||V>n.bottom);x.location.x=w,x.location.y=V}o.push(n,x),o.push(n,r)}else n.body=r}},v=function(e){var t,n,o,s,c=i,f=1,l=0,h=1;for(c[0]=d;f;){var p=c[l],v=p.body;f-=1,l+=1,v&&v!==e?(n=v.location.x-e.location.x,o=v.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=p.massX/p.mass-e.location.x,o=p.massY/p.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(p.right-p.left)/s?(t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(p.quads[0]&&(c[h]=p.quads[0],f+=1,h+=1),p.quads[1]&&(c[h]=p.quads[1],f+=1,h+=1),p.quads[2]&&(c[h]=p.quads[2],f+=1,h+=1),p.quads[3]&&(c[h]=p.quads[3],f+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,c=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>c&&(r=c),c>o&&(o=c)}var h=i-n,v=o-r;for(h>v?o=r+h:i=n+v,f=0,d=l(),d.left=n,d.right=i,d.top=r,d.bottom=o,t=u;t--;)p(a[t],d)};return{insert:p,init:m,update:v,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{init:function(){},update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{init:function(){},update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var c=s-o,f=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*c/s*n.weight;r.force.x+=f*a,r.force.y+=f*u,i.force.x+=-f*a,i.force.y+=-f*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t=e,n=[],r=[],i=[],o=[];return{speedLimit:1,bodies:n,accumulate:function(){var e,t,a;for(e=i.length;e--;)i[e].init(this);for(e=o.length;e--;)o[e].init(this);for(e=n.length;e--;)for(a=n[e],a.force.x=0,a.force.y=0,t=0;i.length>t;t++)i[t].update(a);for(e=0;r.length>e;++e)for(t=0;o.length>t;t++)o[t].update(r[e])},run:function(e){return this.accumulate(),t.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return n.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,n);return 0>t?!1:n.splice(t,1)},addSpring:function(e,t,n,i,o){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};i="number"==typeof i?i:1;var a=new Viva.Graph.Physics.Spring(e,t,n,o>=0?o:-1,i);return r.push(a),a},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,r);return 0>t?!1:r.splice(t,1)},addBodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};i.push(e)},addSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};o.push(e)}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),c=function(n){var r=(u.x1+u.x2)/2,i=(u.y1+u.y2)/2,o=t.springLength;if(n.links&&n.links.length>0){var a=n.links[0],c=a.fromId!==n.id?e.getNode(a.fromId):e.getNode(a.toId);c.position&&(r=c.position.x,i=c.position.y)}return{x:r+s.next(o)-o/2,y:i+s.next(o)-o/2}},f=function(t){var n=t.force_directed_body;n.mass=1+e.getLinks(t.id).length/3},l=function(e){var t=e.force_directed_body;t||(e.position=e.position||c(e),t=new Viva.Graph.Physics.Body,e.force_directed_body=t,f(e),t.loc(e.position),r.addBody(t))},d=function(e){var t=e.force_directed_body;t&&(e.force_directed_body=null,delete e.force_directed_body,r.removeBody(t))},h=function(t){var n=e.getNode(t.fromId),i=e.getNode(t.toId);f(n),f(i),t.force_directed_spring=r.addSpring(n.force_directed_body,i.force_directed_body,-1,t.weight)},p=function(t){var n=t.force_directed_spring;if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&f(i),o&&f(o),t.force_directed_spring=null,delete t.force_directed_spring,r.removeSpring(n)}},v=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&l(n.node),n.link&&h(n.link)):"remove"===n.changeType&&(n.node&&d(n.node),n.link&&p(n.link))}},m=function(){e.forEachNode(l),e.forEachLink(h),e.addEventListener("changed",v)},g=function(e){return e?e.isPinned||e.data&&e.data.isPinned:!0},y=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;0!==e.getNodesCount()&&(e.forEachNode(function(e){var o=e.force_directed_body;o&&(g(e)&&o.loc(e.position),e.position.x=o.location.x,e.position.y=o.location.y,t>e.position.x&&(t=e.position.x),e.position.x>r&&(r=e.position.x),n>e.position.y&&(n=e.position.y),e.position.y>i&&(i=e.position.y))}),u.x1=t,u.x2=r,u.y1=n,u.y2=i)};return r.addSpringForce(o),r.addBodyForce(i),r.addBodyForce(a),m(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(20);return y(),n>e},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",v)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.position.xt.x2&&(t.x2=e.position.x),e.position.yt.y2&&(t.y2=e.position.y)},a=function(e){e.hasOwnProperty("position")||(e.position=i(e)),o(e,r)},u=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(a))},s=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&a(n.node)}};return{run:function(){this.step()},step:function(){return u(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",s)},placeNode:function(e){return"function"==typeof e?(i=e,u(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,c=t.container,f=!1,l=!0,d=0,h=0,p=!1,v=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){c=c||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:c}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x={x:0,y:0,node:null},w={x:0,y:0,node:null},V={x:0,y:0},b=Viva.Graph.Utils.events(window),E=Viva.Graph.Utils.events({}).extend(),G=function(t){var n=e.getNode(t.fromId),r=e.getNode(t.toId);n&&r&&(x.x=n.position.x,x.y=n.position.y,x.node=n,w.x=r.position.x,w.y=r.position.y,w.node=r,s.updateLinkPosition(t.ui,x,w))},P=function(e){V.x=e.position.x,V.y=e.position.y,s.updateNodePosition(e.ui,V)},N=function(){s.beginRender(),t.renderLinks&&!s.omitLinksRendering&&e.forEachLink(G),e.forEachNode(P),s.endRender()},_=function(){return p=u.step()&&!v,N(),!p},L=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return _()},n)):(d=0,h=0,i=Viva.Graph.Utils.timer(_,n)),void 0)},A=function(){p=!1,i.restart()},I=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},k=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(c);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),l=!1},T=function(e){var t=s.node(e);e.ui=t,s.initNode(t),P(e)},C=function(e){e.hasOwnProperty("ui")&&(s.releaseNode(e.ui),e.ui=null,delete e.ui)},M=function(e){var t=s.link(e);e.ui=t,s.initLink(t),s.omitLinksRendering||G(e)},S=function(e){e.hasOwnProperty("ui")&&(s.releaseLink(e.ui),e.ui=null,delete e.ui)},U=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=e.isPinned,e.isPinned=!0,v=!0,A()},onDrag:function(t,n){e.position.x+=n.x/g.scale,e.position.y+=n.y/g.scale,v=!0,N()},onStop:function(){e.isPinned=t,v=!1}})},R=function(e){r.bindDragNDrop(e,null)},D=function(){s.init(c),e.forEachNode(T),t.renderLinks&&e.forEachLink(M)},F=function(){s.release(c)},O=function(t){var n=t.node;"add"===t.changeType?(T(n),U(n),l&&k()):"remove"===t.changeType?(R(n),C(n),0===e.getNodesCount()&&(l=!0)):"update"===t.changeType&&(R(n),C(n),T(n),U(n))},z=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&M(n);else if("remove"===e.changeType)t.renderLinks&&S(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},B=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?O(n):n.link&&z(n);A()},Y=function(){k(),_()},X=function(){a&&(a.release(),a=null)},q=function(){o&&(o.stop("changed",B),o=null)},W=function(){b.on("resize",Y),X(),a=Viva.Graph.Utils.dragndrop(c),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),N()}),a.onScroll(function(e,t,n){var r=Math.pow(1.4,0>t?-.2:.2);g.scale=s.scale(r,n),N(),E.fire("scale",g.scale)}),e.forEachNode(U),q(),o=Viva.Graph.Utils.events(e),o.on("changed",B)},j=function(){f=!1,q(),X(),b.stop("resize",Y),E.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&S(e)}),e.forEachNode(function(e){R(e),C(e)}),u.dispose(),F()};return{run:function(e){return f||(y(),I(),k(),D(),W(),f=!0),L(e),this},reset:function(){s.resetScale(),k(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return N(),this},dispose:function(){j()},on:function(e,t){return E.addEventListener(e,t),this},off:function(e,t){return E.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var c=n(u.nodes[a]);if(!c.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(c.id,c.data)}for(a=0;u.links.length>a;++a){var f=o(u.links[a]);if(!f.hasOwnProperty("fromId")||!f.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(f.fromId,f.toId,f.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},c={},f=[t.id],l=function(e){c.hasOwnProperty(e.id)||(f.push(e.id),c[e.id]=i+1),c[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),c[t.id]=0,s[t.id]=1;f.length;)r=f.shift(),i=c[r],o=s[r],u.push(r),e.forEachLinkedNode(r,l,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},c=t.S;for(r=0;c.length>r;r+=1)s[c[r]]=0;for(;c.length;){for(i=c.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r); -return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},c=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},f=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},l=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},d=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?l(e):(l=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,d()},translateRel:function(e,r){t+=e,n+=r,d()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return c=e,this},placeLink:function(e){return f=e,this},init:function(t){e=t,d()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){c(e,t)},updateLinkPosition:function(e,t,n){f(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var c=r.childNodes[t];if(1===c.nodeType){var f=c.attr("class"),l=c.attr("id"),d=c.nodeName;if(a&&f){for(f=f.replace(/\s+/g," ").split(" "),n=0;f.length>n;n++)if(a&&f[n]===e.substr(1)){i.push(Viva.Graph.svg(c));break}}else{if(u&&l===e.substr(1)){i.push(Viva.Graph.svg(c));break}s&&d===e&&i.push(Viva.Graph.svg(c))}i=i.concat(Viva.Graph.svg(c).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i=1,o=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},a=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},u=function(){return Viva.Graph.svg("line").attr("stroke","#999")},s=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},c=function(e){e.fire("rescaled")},f=function(){if(e){var t="matrix("+i+", 0, 0,"+i+","+n+","+r+")";e.attr("transform",t)}},l={node:function(e){return e&&"function"!=typeof e?o(e):(o=e,this)},link:function(e){return e&&"function"!=typeof e?u(e):(u=e,this)},placeNode:function(e){return a=e,this},placeLink:function(e){return s=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,f()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(o,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(o).translate(-u.x,-u.y),f=e.getCTM().multiply(s);i=f.a,n=f.e,r=f.f;var l="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",l),c(this),i},resetScale:function(){i=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),c(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),f()},release:function(e){t&&e&&e.removeChild(t)},initLink:function(t){t&&(e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t))},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){a(e,t)},updateLinkPosition:function(e,t,n){s(e,t,n)},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(l).extend(),l},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),c=e.position,f=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,c.x,c.y)||r,l=n.intersectRect(c.x-s.w/2,c.y-s.h/2,c.x+s.w/2,c.y+s.h/2,c.x,c.y,r.x,r.y)||c;o+="M"+Math.round(f.x)+" "+Math.round(f.y)+"L"+Math.round(l.x)+" "+Math.round(l.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,c=4,f=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),d=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*f),p=new Float32Array(h),v=new Uint32Array(h),m=0,g=function(){if((m+1)*f>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(v),p=t,v=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(d,l),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;p[n*c]=t.x,p[n*c+1]=t.y,p[n*c+2]=e.size,v[n*c+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(v,e.id*c,m*c,c)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,c*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,c*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,c,f=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),p=0,v=new ArrayBuffer(16*l),m=new Float32Array(v),g=new Uint32Array(v),y=function(){if((p+1)*l>v.byteLength){var e=new ArrayBuffer(2*v.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,v=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,d),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*f;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),p+=1,o=e.id},removeLink:function(e){p>0&&(p-=1),p>e.id&&p>0&&r.copyArrayPart(g,e.id*f,p*f,f)},updateTransform:function(e){c=!0,s=e},updateSize:function(e,t){a=e,u=t,c=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,v,t.DYNAMIC_DRAW),c&&(c=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*p),o=p-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*f,o*f,f),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],c=[],f=function(e){return 0===(e&e-1)},l=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},d=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},p=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},v=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=d(e),o={offset:e};r.textureNumber>=s.length&&l();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),c[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!f(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=d(t.offset),r=d(o);v(r,n);var i=a[c[o]];return i.offset=t.offset,c[t.offset]=c[o],p(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){p(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,c,f=18,l=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),d=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,p=0,v=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(d,l),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*f;v[n]=t.x-e.size,v[n+1]=t.y-e.size,v[n+2]=4*e._offset,v[n+3]=t.x+e.size,v[n+4]=t.y-e.size,v[n+5]=4*e._offset+1,v[n+6]=t.x-e.size,v[n+7]=t.y+e.size,v[n+8]=4*e._offset+2,v[n+9]=t.x-e.size,v[n+10]=t.y+e.size,v[n+11]=4*e._offset+2,v[n+12]=t.x+e.size,v[n+13]=t.y-e.size,v[n+14]=4*e._offset+1,v[n+15]=t.x+e.size,v[n+16]=t.y+e.size,v[n+17]=4*e._offset+3},createNode:function(t){v=i.extendArray(v,p,f),p+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){p>0&&(p-=1),p>t.id&&p>0&&(t.src&&e.remove(t.src),i.copyArrayPart(v,t.id*f,p*f,f))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){c=!0,s=e},updateSize:function(e,t){a=e,u=t,c=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,v,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*p)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,c,f=0,l=0,d=[],h=[],p=Viva.Graph.View.webglLinkProgram(),v=Viva.Graph.View.webglNodeProgram(),m=function(){return Viva.Graph.View.webglSquare()},g=function(){return Viva.Graph.View.webglLine(3014898687)},y=function(){p.updateTransform(a),v.updateTransform(a)},x=function(){a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},w=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),p&&p.updateSize(i/2,o/2),v&&v.updateSize(i/2,o/2))},V=function(e){var t=f++,n=m(e);return n.id=t,v.createNode(n),d[t]=e,n},b=function(e){var t=l++,n=g(e);return n.id=t,p.createLink(n),h[t]=e,n},E=function(e){e.fire("rescaled")},G={node:function(e){return e&&"function"!=typeof e?V(e):(m=e,this)},link:function(e){return e&&"function"!=typeof e?b(e):(g=e,this)},placeNode:function(e){return u=e,this},placeLink:function(e){return s=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){l>0&&p.render(),f>0&&v.render()},bringLinkToFront:function(e){var t,n,r=p.getFrontLinkId();p.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].ui.id=r,h[t]=n,h[t].ui.id=t)},graphCenterChanged:function(){w()},initLink:function(){},initNode:function(){},translateRel:function(e,t){a[12]+=2*a[0]*e/i/a[0],a[13]-=2*a[5]*t/o/a[5],y()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=a[12],r-=a[13],a[12]+=n*(1-e),a[13]+=r*(1-e),a[0]*=e,a[5]*=e,y(),E(this),a[0]},resetScale:function(){return x(),r&&(w(),y()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),w(),x(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var s="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(s),s}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var f=e.clearColorValue;r.clearColor(f.r,f.g,f.b,f.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}p.load(r),p.updateSize(i/2,o/2),v.load(r),v.updateSize(i/2,o/2),y(),"function"==typeof c&&c(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){l>0&&(l-=1),p.removeLink(e);var t=e.id;if(l>t){if(0===l||l===t)return;h[t]=h[l],h[t].ui.id=t}},releaseNode:function(e){if(f>0&&(f-=1),v.removeNode(e),f>e.id){var t=e.id;if(0===f||f===t)return;var n=d[f],r=d[t];d[t]=n,d[t].ui.id=t,v.replaceProperties(r.ui,n.ui)}},updateNodePosition:function(e,t){t.y=-t.y,u&&u(e,t),v.position(e,t)},updateLinkPosition:function(e,t,n){t.y=-t.y,n.y=-n.y,s&&s(e,t,n),p.position(e,t,n)},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):c=e),n},setNodeProgram:function(e){if(!r&&e)v=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)p=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},getGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-a[12])/a[0],e.y=(e.y-a[13])/a[5],e.x*=i/2,e.y*=-o/2,e}};return Viva.Graph.Utils.events(G).extend(),G},Viva.Graph.webglInputEvents=function(e,t){if(e.webglInputEvents)return e.webglInputEvents;var n,r,i=function(e,t,n){if(e.ui&&e.ui.size){var r=e.position,i=e.ui.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},o=null,a=Viva.Graph.spatialIndex(t,i),u=[],s=[],c=[],f=[],l=[],d=[],h=[],p=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},m=function(e){return v(e),!1},g=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},y=function(t){var i={x:0,y:0},y=null,x=+new Date,w=function(e){g(l,[y,e]),i.x=e.clientX,i.y=e.clientY},V=function(){p.stop("mousemove",w),p.stop("mouseup",V)},b=function(){r=t.getBoundingClientRect()};window.addEventListener("resize",b),b(),t.addEventListener("mousemove",function(t){if(!o){var n,c=!1;i.x=t.clientX-r.left,i.y=t.clientY-r.top,e.getGraphCoordinates(i),n=a.getNodeAt(i.x,i.y),n&&y!==n?(y=n,c=c||g(u,[y])):null===n&&y!==n&&(c=c||g(s,[y]),y=null),c&&v(t)}}),t.addEventListener("mousedown",function(t){var o,u=!1;i.x=t.clientX-r.left,i.y=t.clientY-r.top,e.getGraphCoordinates(i),o=[a.getNodeAt(i.x,i.y),t],o[0]?(u=g(c,o),p.on("mousemove",w),p.on("mouseup",V),n=window.document.onselectstart,window.document.onselectstart=m,y=o[0]):y=null,u&&v(t)}),t.addEventListener("mouseup",function(t){var o,u=+new Date;i.x=t.clientX-r.left,i.y=t.clientY-r.top,e.getGraphCoordinates(i),o=[a.getNodeAt(i.x,i.y),t],o[0]&&(window.document.onselectstart=n,400>u-x&&o[0]===y?g(h,o):g(d,o),x=u,g(f,o)&&v(t))})};return e.getGraphicsRoot(y),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&u.push(e),this},mouseLeave:function(e){return"function"==typeof e&&s.push(e),this},mouseDown:function(e){return"function"==typeof e&&c.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&l.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&h.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t,e),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.ui.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.ui.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.ui.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.ui.id]=t}}}; \ No newline at end of file +var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.4.2",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){function e(){var e=4022871197,t=function(t){var n;for(t=""+t,n=0;t.length>n;n++){e+=t.charCodeAt(n);var r=.02519603282416938*e;e=r>>>0,r-=e,r*=e,e=r>>>0,r-=e,e+=4294967296*r}return 2.3283064365386963e-10*(e>>>0)};return t.version="Mash 0.9",t}function t(t){return function(t){var n,r,i=0,o=58,a=119,u=178,s=[],c=e();for(0===t.length&&(t=[+new Date]),n=0;256>n;n++)s[n]=c(" "),s[n]-=4.76837158203125e-7*c(" "),0>s[n]&&(s[n]+=1);for(r=0;t.length>r;r++)for(n=0;256>n;n++)s[n]-=c(t[r]),s[n]-=4.76837158203125e-7*c(t[r]),0>s[n]&&(s[n]+=1);c=null;var f=function(){var e;return i=255&i+1,o=255&o+1,a=255&a+1,u=255&u+1,e=s[i]-s[o],0>e&&(e+=1),e-=s[a],0>e&&(e+=1),e-=s[u],0>e&&(e+=1),s[i]=e,e};return f.uint32=function(){return 4294967296*f()>>>0},f.fract53=f,f.version="LFIB4 0.9",f.args=t,f}(t)}var n=new t(Array.prototype.slice.call(arguments));return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),c=Viva.Graph.Utils.events(e),f=Viva.Graph.Utils.findElementPosition,l=0,d=0,h=!1,p=0,v=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-l,y:r-d}),l=t,d=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(l=e.clientX,d=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:l,y:d}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},E=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=v(t),o=f(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},G=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",E,!1):e.addEventListener("DOMMouseScroll",E,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",E,!1):e.removeEventListener("DOMMouseScroll",E,!1)),i=t},P=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},_=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=P(e.touches[0],e.touches[1]),r=0;p>n?r=-1:n>p&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),p=n,g(e),y(e)}},N=function(e){h=!1,s.stop("touchmove",_),s.stop("touchend",N),s.stop("touchcancel",N),u=null,r&&r(e)},L=function(e,n){g(e),y(e),l=n.clientX,d=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:l,y:d}),h||(h=!0,s.on("touchmove",_),s.on("touchend",N),s.on("touchcancel",N))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?L(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),p=P(t.touches[0],t.touches[1])),void 0)};return c.on("mousedown",V),c.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return G(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",_),s.stop("touchend",N),s.stop("touchcancel",N),G(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(){return{bindDragNDrop:function(e,t){if(t){var n=Viva.Graph.Utils.dragndrop(e.ui);"function"==typeof t.onStart&&n.onStart(t.onStart),"function"==typeof t.onDrag&&n.onDrag(t.onDrag),"function"==typeof t.onStop&&n.onStop(t.onStop),e.events=n}else e.events&&(e.events.release(),e.events=null,delete e.events)}}},Viva.Graph.spatialIndex=function(e,t){var n,r,i=16;return"function"==typeof t?(r=t,n=function(t,n){var i=null;return e.forEachNode(function(e){return r(e,t,n)?(i=e,!0):void 0}),i}):"number"==typeof t&&(i=t,n=function(t,n){var r=null;return e.forEachNode(function(e){var o=e.position;return t>o.x-i&&o.x+i>t&&n>o.y-i&&o.y+i>n?(r=e,!0):void 0}),r}),{getNodeAt:n}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,c,f,l,d,h,p,v,m,g,y,x,w,V={x:0,y:0};return s=r-t,f=e-n,d=n*t-e*r,m=s*i+f*o+d,g=s*a+f*u+d,0!==m&&0!==g&&m>=0==g>=4?null:(c=u-o,l=i-a,h=a*o-i*u,p=c*e+l*t+h,v=c*n+l*r+h,0!==p&&0!==v&&p>=0==v>=0?null:(y=s*l-c*f,0===y?null:(x=0>y?-y/2:y/2,x=0,w=f*h-l*d,V.x=(0>w?w-x:w+x)/y,w=c*d-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,c=a.y-e.y,f=s*s+c*c;for(r=1;o.length>r;++r){a=o[r];var l=i(a);l===u?(s=a.x-e.x,c=a.y-e.y,n=s*s+c*c,f>n?o.splice(r,1):o.splice(r-1,1)):u=l}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n){this.fromId=e,this.toId=t,this.data=n},Viva.Graph.graph=function(){var e={},t=[],n=0,r=0,i=[],o=function(e){e.fire("changed",i)},a=function(){r+=1},u=function(e){r-=1,0===r&&i.length>0&&(o(e),i.length=0)},s=function(e,t){i.push({node:e,changeType:t})},c=function(e,t){i.push({link:e,changeType:t})},f=function(e){return e&&"object"==typeof e&&"number"==typeof e.length&&"function"==typeof e.splice&&!e.propertyIsEnumerable("length")},l={addNode:function(t,r){if(t===void 0)throw{message:"Invalid node identifier"};a();var i=this.getNode(t);if(i?s(i,"update"):(i=new Viva.Graph.Node(t),n++,s(i,"add")),r){var o,c=i.data||{},l=typeof r;if("string"===l||f(r)||"number"===l||"boolean"===l)c=r;else if("undefined"===l)c=null;else for(o in r)r.hasOwnProperty(o)&&(c[o]=r[o]);i.data=c}return e[t]=i,u(this),i},addLink:function(e,n,r){a();var i=this.getNode(e)||this.addNode(e),o=this.getNode(n)||this.addNode(n),s=new Viva.Graph.Link(e,n,r);return t.push(s),i.links.push(s),o.links.push(s),c(s,"add"),u(this),s},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;a(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),u(this),!0},removeNode:function(t){var r=this.getNode(t);if(!r)return!1;for(a();r.links.length;){var i=r.links[0];this.removeLink(i)}e[t]=null,delete e[t],n--,s(r,"remove"),u(this)},getNode:function(t){return e[t]},getNodesCount:function(){return n},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n;if("function"==typeof e)for(n=0;t.length>n;++n)e(t[n])},beginUpdate:function(){a()},endUpdate:function(){u(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(l).extend(),l},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var c=u.velocity.x,f=u.velocity.y,l=Math.sqrt(c*c+f*f);l>r&&(u.velocity.x=r*c/l,u.velocity.y=r*f/l),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},c=[],f=0,l=function(){var e;return c[f]?(e=c[f],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,c[f]=e),++f,e},d=l(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return.01>n&&.01>r},p=function(e){for(o.reset(),o.push(d,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,c=n.left,f=(n.right+c)/2,p=n.top,v=(n.bottom+p)/2;if(i>f){s+=1;var m=c;c=f,f+=f-m}if(a>v){s+=2;var g=p;p=v,v+=v-g}var y=n.quads[s];y||(y=l(),y.left=c,y.top=p,y.right=f,y.bottom=v,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){var w,V;do{var b=2*u.nextDouble()*Math.PI,E=.006*(n.right-n.left)*Math.cos(b),G=.006*(n.bottom-n.top)*Math.sin(b);w=x.location.x+E,V=x.location.y+G}while(n.left>w||w>n.right||n.top>V||V>n.bottom);x.location.x=w,x.location.y=V}o.push(n,x),o.push(n,r)}else n.body=r}},v=function(e){var t,n,o,s,c=i,f=1,l=0,h=1;for(c[0]=d;f;){var p=c[l],v=p.body;f-=1,l+=1,v&&v!==e?(n=v.location.x-e.location.x,o=v.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=p.massX/p.mass-e.location.x,o=p.massY/p.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(p.right-p.left)/s?(t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(p.quads[0]&&(c[h]=p.quads[0],f+=1,h+=1),p.quads[1]&&(c[h]=p.quads[1],f+=1,h+=1),p.quads[2]&&(c[h]=p.quads[2],f+=1,h+=1),p.quads[3]&&(c[h]=p.quads[3],f+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,c=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>c&&(r=c),c>o&&(o=c)}var h=i-n,v=o-r;for(h>v?o=r+h:i=n+v,f=0,d=l(),d.left=n,d.right=i,d.top=r,d.bottom=o,t=u;t--;)p(a[t],d)};return{insert:p,init:m,update:v,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{init:function(){},update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{init:function(){},update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var c=s-o,f=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*c/s*n.weight;r.force.x+=f*a,r.force.y+=f*u,i.force.x+=-f*a,i.force.y+=-f*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t=e,n=[],r=[],i=[],o=[];return{speedLimit:1,bodies:n,accumulate:function(){var e,t,a;for(e=i.length;e--;)i[e].init(this);for(e=o.length;e--;)o[e].init(this);for(e=n.length;e--;)for(a=n[e],a.force.x=0,a.force.y=0,t=0;i.length>t;t++)i[t].update(a);for(e=0;r.length>e;++e)for(t=0;o.length>t;t++)o[t].update(r[e])},run:function(e){return this.accumulate(),t.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return n.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,n);return 0>t?!1:n.splice(t,1)},addSpring:function(e,t,n,i,o){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};i="number"==typeof i?i:1;var a=new Viva.Graph.Physics.Spring(e,t,n,o>=0?o:-1,i);return r.push(a),a},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,r);return 0>t?!1:r.splice(t,1)},addBodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};i.push(e)},addSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};o.push(e)}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02,springTransform:function(){}});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),c=function(n){var r=(u.x1+u.x2)/2,i=(u.y1+u.y2)/2,o=t.springLength;if(n.links&&n.links.length>0){var a=n.links[0],c=a.fromId!==n.id?e.getNode(a.fromId):e.getNode(a.toId);c.position&&(r=c.position.x,i=c.position.y)}return{x:r+s.next(o)-o/2,y:i+s.next(o)-o/2}},f=function(t){var n=t.force_directed_body;n.mass=1+e.getLinks(t.id).length/3},l=function(e){var t=e.force_directed_body;t||(e.position=e.position||c(e),t=new Viva.Graph.Physics.Body,e.force_directed_body=t,f(e),t.loc(e.position),r.addBody(t))},d=function(e){var t=e.force_directed_body;t&&(e.force_directed_body=null,delete e.force_directed_body,r.removeBody(t))},h=function(n){var i=e.getNode(n.fromId),o=e.getNode(n.toId);f(i),f(o),n.force_directed_spring=r.addSpring(i.force_directed_body,o.force_directed_body,-1,n.weight),t.springTransform(n,n.force_directed_spring)},p=function(t){var n=t.force_directed_spring;if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&f(i),o&&f(o),t.force_directed_spring=null,delete t.force_directed_spring,r.removeSpring(n)}},v=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&l(n.node),n.link&&h(n.link)):"remove"===n.changeType&&(n.node&&d(n.node),n.link&&p(n.link))}},m=function(){e.forEachNode(l),e.forEachLink(h),e.addEventListener("changed",v)},g=function(e){return e?e.isPinned||e.data&&e.data.isPinned:!0},y=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;0!==e.getNodesCount()&&(e.forEachNode(function(e){var o=e.force_directed_body;o&&(g(e)&&o.loc(e.position),e.position.x=o.location.x,e.position.y=o.location.y,t>e.position.x&&(t=e.position.x),e.position.x>r&&(r=e.position.x),n>e.position.y&&(n=e.position.y),e.position.y>i&&(i=e.position.y))}),u.x1=t,u.x2=r,u.y1=n,u.y2=i)};return r.addSpringForce(o),r.addBodyForce(i),r.addBodyForce(a),m(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(20);return y(),n>e},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",v)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.position.xt.x2&&(t.x2=e.position.x),e.position.yt.y2&&(t.y2=e.position.y)},a=function(e){e.hasOwnProperty("position")||(e.position=i(e)),o(e,r)},u=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(a))},s=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&a(n.node)}};return{run:function(){this.step()},step:function(){return u(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",s)},placeNode:function(e){return"function"==typeof e?(i=e,u(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,c=t.container,f=!1,l=!0,d=0,h=0,p=!1,v=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){c=c||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:c}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x={x:0,y:0,node:null},w={x:0,y:0,node:null},V={x:0,y:0},b=Viva.Graph.Utils.events(window),E=Viva.Graph.Utils.events({}).extend(),G=function(t){var n=e.getNode(t.fromId),r=e.getNode(t.toId);n&&r&&(x.x=n.position.x,x.y=n.position.y,x.node=n,w.x=r.position.x,w.y=r.position.y,w.node=r,s.updateLinkPosition(t.ui,x,w))},P=function(e){V.x=e.position.x,V.y=e.position.y,s.updateNodePosition(e.ui,V)},_=function(){s.beginRender(),t.renderLinks&&!s.omitLinksRendering&&e.forEachLink(G),e.forEachNode(P),s.endRender()},N=function(){return p=u.step()&&!v,_(),!p},L=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return N()},n)):(d=0,h=0,i=Viva.Graph.Utils.timer(N,n)),void 0)},A=function(){p=!1,i.restart()},I=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},k=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(c);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),l=!1},T=function(e){var t=s.node(e);e.ui=t,s.initNode(t),P(e)},C=function(e){e.hasOwnProperty("ui")&&(s.releaseNode(e.ui),e.ui=null,delete e.ui)},M=function(e){var t=s.link(e);e.ui=t,s.initLink(t),s.omitLinksRendering||G(e)},S=function(e){e.hasOwnProperty("ui")&&(s.releaseLink(e.ui),e.ui=null,delete e.ui)},U=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=e.isPinned,e.isPinned=!0,v=!0,A()},onDrag:function(t,n){e.position.x+=n.x/g.scale,e.position.y+=n.y/g.scale,v=!0,_()},onStop:function(){e.isPinned=t,v=!1}})},R=function(e){r.bindDragNDrop(e,null)},D=function(){s.init(c),e.forEachNode(T),t.renderLinks&&e.forEachLink(M)},F=function(){s.release(c)},O=function(t){var n=t.node;"add"===t.changeType?(T(n),U(n),l&&k()):"remove"===t.changeType?(R(n),C(n),0===e.getNodesCount()&&(l=!0)):"update"===t.changeType&&(R(n),C(n),T(n),U(n))},z=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&M(n);else if("remove"===e.changeType)t.renderLinks&&S(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},B=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?O(n):n.link&&z(n);A()},Y=function(){k(),N()},X=function(){a&&(a.release(),a=null)},q=function(){o&&(o.stop("changed",B),o=null)},W=function(){b.on("resize",Y),X(),a=Viva.Graph.Utils.dragndrop(c),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),_()}),a.onScroll(function(e,t,n){var r=Math.pow(1.4,0>t?-.2:.2);g.scale=s.scale(r,n),_(),E.fire("scale",g.scale)}),e.forEachNode(U),q(),o=Viva.Graph.Utils.events(e),o.on("changed",B)},j=function(){f=!1,q(),X(),b.stop("resize",Y),E.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&S(e)}),e.forEachNode(function(e){R(e),C(e)}),u.dispose(),F()};return{run:function(e){return f||(y(),I(),k(),D(),W(),f=!0),L(e),this},reset:function(){s.resetScale(),k(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return _(),this},dispose:function(){j()},on:function(e,t){return E.addEventListener(e,t),this},off:function(e,t){return E.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var c=n(u.nodes[a]);if(!c.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(c.id,c.data)}for(a=0;u.links.length>a;++a){var f=o(u.links[a]);if(!f.hasOwnProperty("fromId")||!f.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(f.fromId,f.toId,f.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},c={},f=[t.id],l=function(e){c.hasOwnProperty(e.id)||(f.push(e.id),c[e.id]=i+1),c[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),c[t.id]=0,s[t.id]=1;f.length;)r=f.shift(),i=c[r],o=s[r],u.push(r),e.forEachLinkedNode(r,l,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},c=t.S;for(r=0;c.length>r;r+=1)s[c[r]]=0;for(;c.length;){for(i=c.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"}; +var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},c=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},f=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},l=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},d=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?l(e):(l=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,d()},translateRel:function(e,r){t+=e,n+=r,d()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return c=e,this},placeLink:function(e){return f=e,this},init:function(t){e=t,d()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){c(e,t)},updateLinkPosition:function(e,t,n){f(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var c=r.childNodes[t];if(1===c.nodeType){var f=c.attr("class"),l=c.attr("id"),d=c.nodeName;if(a&&f){for(f=f.replace(/\s+/g," ").split(" "),n=0;f.length>n;n++)if(a&&f[n]===e.substr(1)){i.push(Viva.Graph.svg(c));break}}else{if(u&&l===e.substr(1)){i.push(Viva.Graph.svg(c));break}s&&d===e&&i.push(Viva.Graph.svg(c))}i=i.concat(Viva.Graph.svg(c).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i=1,o=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},a=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},u=function(){return Viva.Graph.svg("line").attr("stroke","#999")},s=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},c=function(e){e.fire("rescaled")},f=function(){if(e){var t="matrix("+i+", 0, 0,"+i+","+n+","+r+")";e.attr("transform",t)}},l={node:function(e){return e&&"function"!=typeof e?o(e):(o=e,this)},link:function(e){return e&&"function"!=typeof e?u(e):(u=e,this)},placeNode:function(e){return a=e,this},placeLink:function(e){return s=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,f()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(o,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(o).translate(-u.x,-u.y),f=e.getCTM().multiply(s);i=f.a,n=f.e,r=f.f;var l="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",l),c(this),i},resetScale:function(){i=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),c(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),f()},release:function(e){t&&e&&e.removeChild(t)},initLink:function(t){t&&(e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t))},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){a(e,t)},updateLinkPosition:function(e,t,n){s(e,t,n)},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(l).extend(),l},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),c=e.position,f=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,c.x,c.y)||r,l=n.intersectRect(c.x-s.w/2,c.y-s.h/2,c.x+s.w/2,c.y+s.h/2,c.x,c.y,r.x,r.y)||c;o+="M"+Math.round(f.x)+" "+Math.round(f.y)+"L"+Math.round(l.x)+" "+Math.round(l.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,c=4,f=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),d=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*f),p=new Float32Array(h),v=new Uint32Array(h),m=0,g=function(){if((m+1)*f>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(v),p=t,v=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(d,l),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;p[n*c]=t.x,p[n*c+1]=t.y,p[n*c+2]=e.size,v[n*c+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(v,e.id*c,m*c,c)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,c*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,c*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,c,f=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),p=0,v=new ArrayBuffer(16*l),m=new Float32Array(v),g=new Uint32Array(v),y=function(){if((p+1)*l>v.byteLength){var e=new ArrayBuffer(2*v.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,v=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,d),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*f;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),p+=1,o=e.id},removeLink:function(e){p>0&&(p-=1),p>e.id&&p>0&&r.copyArrayPart(g,e.id*f,p*f,f)},updateTransform:function(e){c=!0,s=e},updateSize:function(e,t){a=e,u=t,c=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,v,t.DYNAMIC_DRAW),c&&(c=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*p),o=p-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*f,o*f,f),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],c=[],f=function(e){return 0===(e&e-1)},l=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},d=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},p=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},v=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=d(e),o={offset:e};r.textureNumber>=s.length&&l();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),c[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!f(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=d(t.offset),r=d(o);v(r,n);var i=a[c[o]];return i.offset=t.offset,c[t.offset]=c[o],p(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){p(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,c,f=18,l=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),d=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,p=0,v=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(d,l),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*f;v[n]=t.x-e.size,v[n+1]=t.y-e.size,v[n+2]=4*e._offset,v[n+3]=t.x+e.size,v[n+4]=t.y-e.size,v[n+5]=4*e._offset+1,v[n+6]=t.x-e.size,v[n+7]=t.y+e.size,v[n+8]=4*e._offset+2,v[n+9]=t.x-e.size,v[n+10]=t.y+e.size,v[n+11]=4*e._offset+2,v[n+12]=t.x+e.size,v[n+13]=t.y-e.size,v[n+14]=4*e._offset+1,v[n+15]=t.x+e.size,v[n+16]=t.y+e.size,v[n+17]=4*e._offset+3},createNode:function(t){v=i.extendArray(v,p,f),p+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){p>0&&(p-=1),p>t.id&&p>0&&(t.src&&e.remove(t.src),i.copyArrayPart(v,t.id*f,p*f,f))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){c=!0,s=e},updateSize:function(e,t){a=e,u=t,c=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,v,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*p)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,c,f=0,l=0,d=[],h=[],p=Viva.Graph.View.webglLinkProgram(),v=Viva.Graph.View.webglNodeProgram(),m=function(){return Viva.Graph.View.webglSquare()},g=function(){return Viva.Graph.View.webglLine(3014898687)},y=function(){p.updateTransform(a),v.updateTransform(a)},x=function(){a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},w=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),p&&p.updateSize(i/2,o/2),v&&v.updateSize(i/2,o/2))},V=function(e){var t=f++,n=m(e);return n.id=t,v.createNode(n),d[t]=e,n},b=function(e){var t=l++,n=g(e);return n.id=t,p.createLink(n),h[t]=e,n},E=function(e){e.fire("rescaled")},G={node:function(e){return e&&"function"!=typeof e?V(e):(m=e,this)},link:function(e){return e&&"function"!=typeof e?b(e):(g=e,this)},placeNode:function(e){return u=e,this},placeLink:function(e){return s=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){l>0&&p.render(),f>0&&v.render()},bringLinkToFront:function(e){var t,n,r=p.getFrontLinkId();p.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].ui.id=r,h[t]=n,h[t].ui.id=t)},graphCenterChanged:function(){w()},initLink:function(){},initNode:function(){},translateRel:function(e,t){a[12]+=2*a[0]*e/i/a[0],a[13]-=2*a[5]*t/o/a[5],y()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=a[12],r-=a[13],a[12]+=n*(1-e),a[13]+=r*(1-e),a[0]*=e,a[5]*=e,y(),E(this),a[0]},resetScale:function(){return x(),r&&(w(),y()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),w(),x(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var s="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(s),s}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var f=e.clearColorValue;r.clearColor(f.r,f.g,f.b,f.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}p.load(r),p.updateSize(i/2,o/2),v.load(r),v.updateSize(i/2,o/2),y(),"function"==typeof c&&c(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){l>0&&(l-=1),p.removeLink(e);var t=e.id;if(l>t){if(0===l||l===t)return;h[t]=h[l],h[t].ui.id=t}},releaseNode:function(e){if(f>0&&(f-=1),v.removeNode(e),f>e.id){var t=e.id;if(0===f||f===t)return;var n=d[f],r=d[t];d[t]=n,d[t].ui.id=t,v.replaceProperties(r.ui,n.ui)}},updateNodePosition:function(e,t){t.y=-t.y,u&&u(e,t),v.position(e,t)},updateLinkPosition:function(e,t,n){t.y=-t.y,n.y=-n.y,s&&s(e,t,n),p.position(e,t,n)},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):c=e),n},setNodeProgram:function(e){if(!r&&e)v=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)p=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},getGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-a[12])/a[0],e.y=(e.y-a[13])/a[5],e.x*=i/2,e.y*=-o/2,e}};return Viva.Graph.Utils.events(G).extend(),G},Viva.Graph.webglInputEvents=function(e,t){if(e.webglInputEvents)return e.webglInputEvents;var n,r,i=function(e,t,n){if(e.ui&&e.ui.size){var r=e.position,i=e.ui.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},o=null,a=Viva.Graph.spatialIndex(t,i),u=[],s=[],c=[],f=[],l=[],d=[],h=[],p=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},m=function(e){return v(e),!1},g=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},y=function(t){var i={x:0,y:0},y=null,x=+new Date,w=function(e){g(l,[y,e]),i.x=e.clientX,i.y=e.clientY},V=function(){p.stop("mousemove",w),p.stop("mouseup",V)},b=function(){r=t.getBoundingClientRect()};window.addEventListener("resize",b),b(),t.addEventListener("mousemove",function(t){if(!o){var n,c=!1;i.x=t.clientX-r.left,i.y=t.clientY-r.top,e.getGraphCoordinates(i),n=a.getNodeAt(i.x,i.y),n&&y!==n?(y=n,c=c||g(u,[y])):null===n&&y!==n&&(c=c||g(s,[y]),y=null),c&&v(t)}}),t.addEventListener("mousedown",function(t){var o,u=!1;i.x=t.clientX-r.left,i.y=t.clientY-r.top,e.getGraphCoordinates(i),o=[a.getNodeAt(i.x,i.y),t],o[0]?(u=g(c,o),p.on("mousemove",w),p.on("mouseup",V),n=window.document.onselectstart,window.document.onselectstart=m,y=o[0]):y=null,u&&v(t)}),t.addEventListener("mouseup",function(t){var o,u=+new Date;i.x=t.clientX-r.left,i.y=t.clientY-r.top,e.getGraphCoordinates(i),o=[a.getNodeAt(i.x,i.y),t],o[0]&&(window.document.onselectstart=n,400>u-x&&o[0]===y?g(h,o):g(d,o),x=u,g(f,o)&&v(t))})};return e.getGraphicsRoot(y),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&u.push(e),this},mouseLeave:function(e){return"function"==typeof e&&s.push(e),this},mouseDown:function(e){return"function"==typeof e&&c.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&l.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&h.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t,e),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.ui.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.ui.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.ui.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.ui.id]=t}}}; \ No newline at end of file diff --git a/src/Layout/forceDirected.js b/src/Layout/forceDirected.js index 3d73e13..4b099ad 100644 --- a/src/Layout/forceDirected.js +++ b/src/Layout/forceDirected.js @@ -41,7 +41,37 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { * Drag force coefficient. Used to slow down system, thus should be less than 1. * The closer it is to 0 the less tight system will be. */ - dragCoeff: 0.02 + dragCoeff: 0.02, + + /** + * Allows to transfor physical spring associated with a link. this allows clients + * to specify custom length for a link. + * + * @param {Viva.Graph.Link} link actual link for which transform is performed + * @param {Viva.Graph.Physics.Spring} spring physical spring which is associated with + * a link. Most interesting property will be 'length' + * + * @example + * // Let's say your graph represent friendship. Each link has associated + * // 'strength' of connection, distributed from 0 (not a strong connection) to + * // 1 (very strong connection) + * // + * // You want your graph to have uniformly distributed links, but stronger + * // connection should pull nodes closer: + * + * graph.addLink(user1, user2, { friendshipStrength: 0.9 }); + * var layout = Viva.Graph.Layout.forceDirected(graph, { + * springLength: 80, // 80 pixels is our ideal link length + * springTransform: function (link, spring) { + * // We can set custom desired length of a spring, based on + * // link's data: + * spring.length = 80 * (1 - link.data.friendshipStrength); + * } + * } + */ + springTransform: function (link, spring) { + // By default, it is a no-op + } }); var forceSimulator = Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()), @@ -121,6 +151,7 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { updateNodeMass(from); updateNodeMass(to); link.force_directed_spring = forceSimulator.addSpring(from.force_directed_body, to.force_directed_body, -1.0, link.weight); + settings.springTransform(link, link.force_directed_spring); }, releaseLink = function(link) { diff --git a/src/version.js b/src/version.js index fc9a685..a8b110f 100644 --- a/src/version.js +++ b/src/version.js @@ -1 +1 @@ -Viva.Graph.version = '0.4.1'; +Viva.Graph.version = '0.4.2'; From 16aff2bb389bce052ddd99af98377507f6f29df9 Mon Sep 17 00:00:00 2001 From: Andrei Kashcha Date: Wed, 20 Nov 2013 22:17:43 -0800 Subject: [PATCH 046/276] Update CHANGELOG --- CHANGELOG | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 255040c..5ff02bc 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,15 +1,15 @@ v0.4.2 date: Nov 20, 2013 - changes: - - Added customization point to force directed layout to allow specify - custom links length. - - Fixed a bug with wrong arguments order in physics simulator. + changes: + - Added customization point to force directed layout to allow specify custom links length. + - Fixed a bug with wrong arguments order in physics simulator. + v0.4.1 date: Jul 20, 2013 - changes: - - Layout algorithm now listens to changes from graph directly. Public API - to add/remove nodes or links is dropped from layout algorithms. - - Added small performance test for node.js + changes: + - Layout algorithm now listens to changes from graph directly. Public API to add/remove nodes or links is dropped from layout algorithms. + - Added small performance test for node.js + v0.4.0 date: April 7, 2013 changes: From eb43f8e907708fd62160cca90c70ccc4198c5d10 Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 20 Nov 2013 22:26:28 -0800 Subject: [PATCH 047/276] Merged with v0.4.2 --- CHANGELOG | 8 +++-- demos/other/customLinkLength.html | 55 +++++++++++++++++++++++++++++++ dist/vivagraph.js | 35 ++++++++++++++++++-- dist/vivagraph.min.js | 4 +-- src/Layout/forceDirected.js | 33 ++++++++++++++++++- src/version.js | 2 +- 6 files changed, 129 insertions(+), 8 deletions(-) create mode 100644 demos/other/customLinkLength.html diff --git a/CHANGELOG b/CHANGELOG index aec8da3..f461962 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,9 @@ +v0.5.1 + date: Nov 20, 2013 + - Merged changes from v0.4.2: custom links length + fixed bug in arguments + order v0.5.0 - data: Oct 20, 2013 + date: Oct 20, 2013 BREAKING CHANGES: - graph.addNode() no longer augments old data model with whatever passed to method. Instead it stores direct reference to passed node's model @@ -10,7 +14,7 @@ v0.5.0 - node/link objects no longer store ui specific properties. Instead you can query them from specific UI provider v0.4.1 - data: Jul 20, 2013 + date: Jul 20, 2013 changes: - Layout algorithm now listens to changes from graph directly. Public API to add/remove nodes or links is dropped from layout algorithms. diff --git a/demos/other/customLinkLength.html b/demos/other/customLinkLength.html new file mode 100644 index 0000000..6350b15 --- /dev/null +++ b/demos/other/customLinkLength.html @@ -0,0 +1,55 @@ + + + + + VivaGraphs test page + + + + + + + Each link has custom length + + diff --git a/dist/vivagraph.js b/dist/vivagraph.js index efc0c8e..af2f8db 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -7,7 +7,7 @@ Viva.Graph = Viva.Graph || {}; if (typeof module !== 'undefined' && module.exports) { module.exports = Viva; } -Viva.Graph.version = '0.5.0'; +Viva.Graph.version = '0.5.1'; /** * Extends target object with given fields/values in the options object. * Unlike jQuery's extend this method does not override target object @@ -2127,7 +2127,37 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { * Drag force coefficient. Used to slow down system, thus should be less than 1. * The closer it is to 0 the less tight system will be. */ - dragCoeff: 0.02 + dragCoeff: 0.02, + + /** + * Allows to transfor physical spring associated with a link. this allows clients + * to specify custom length for a link. + * + * @param {Viva.Graph.Link} link actual link for which transform is performed + * @param {Viva.Graph.Physics.Spring} spring physical spring which is associated with + * a link. Most interesting property will be 'length' + * + * @example + * // Let's say your graph represent friendship. Each link has associated + * // 'strength' of connection, distributed from 0 (not a strong connection) to + * // 1 (very strong connection) + * // + * // You want your graph to have uniformly distributed links, but stronger + * // connection should pull nodes closer: + * + * graph.addLink(user1, user2, { friendshipStrength: 0.9 }); + * var layout = Viva.Graph.Layout.forceDirected(graph, { + * springLength: 80, // 80 pixels is our ideal link length + * springTransform: function (link, spring) { + * // We can set custom desired length of a spring, based on + * // link's data: + * spring.length = 80 * (1 - link.data.friendshipStrength); + * } + * } + */ + springTransform: function (link, spring) { + // By default, it is a no-op + } }); var forceSimulator = Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()), @@ -2242,6 +2272,7 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { toBody = getBody(link.toId), spring = forceSimulator.addSpring(fromBody, toBody, -1.0, link.weight); + settings.springTransform(link, spring); springs[link.id] = spring; }, diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 3abe7a6..d0c8406 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.0",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},P=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},N=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",P,!1):e.addEventListener("DOMMouseScroll",P,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",P,!1):e.removeEventListener("DOMMouseScroll",P,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),N(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,d=Math.sqrt(f*f+c*c);d>r&&(u.velocity.x=r*f/d,u.velocity.y=r*c/d),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};r="number"==typeof r?r:1;var o=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,r);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),f={},c=function(e){if(e.position)return e.position;var n=(u.x1+u.x2)/2,r=(u.y1+u.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],a=o.fromId!==e.id?f[o.fromId]:f[o.toId];a&&a.location&&(n=a.location.x,r=a.location.y)}return{x:n+s.next(i)-i/2,y:r+s.next(i)-i/2}},d=function(e){return f[e]},l=function(e){f[e]=null,delete f[e]},h={},v=function(t){var n=d(t);n.mass=1+e.getLinks(t).length/3},p=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},m=function(e){return e.isPinned},g=function(t){var n=d(t);if(!n){var i=e.getNode(t);if(!i)return;n=new Viva.Graph.Physics.Body,f[t]=n;var o=c(i);n.loc(o),v(t),p(i)&&(n.isPinned=!0),r.addBody(n)}},y=function(e){g(e.id)},x=function(t){var n=d(t.id);n&&(l(t.id),r.removeBody(n),0===e.getNodesCount()&&(u.x1=u.y1=0,u.x2=u.y2=0))},w=function(e){v(e.fromId),v(e.toId);var t=d(e.fromId),n=d(e.toId),i=r.addSpring(t,n,-1,e.weight);h[e.id]=i},V=function(t){var n=h[t.id];if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&v(i.id),o&&v(o.id),delete h[t.id],r.removeSpring(n)}},b=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&g(n.node.id),n.link&&w(n.link)):"remove"===n.changeType&&(n.node&&x(n.node),n.link&&V(n.link))}},P=function(){e.forEachNode(y),e.forEachLink(w),e.addEventListener("changed",b)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in f)if(f.hasOwnProperty(o)){var a=f[o];m(a)?(a.location.x=a.prevLocation.x,a.location.y=a.prevLocation.y):(a.prevLocation.x=a.location.x,a.prevLocation.y=a.location.y),t>a.location.x&&(t=a.location.x),a.location.x>r&&(r=a.location.x),n>a.location.y&&(n=a.location.y),a.location.y>i&&(i=a.location.y)}u.x1=t,u.x2=r,u.y1=n,u.y2=i}};return r.setSpringForce(o),r.setNbodyForce(i),r.setDragForce(a),P(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(20);return N(),n>e},isNodePinned:function(e){var t=d(e.id);return t?m(t):void 0},pinNode:function(e,t){var n=d(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=d(e);return t||(g(e),t=d(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=d(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",b)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a={},u=function(e){e&&(a[e.id]||(a[e.id]=i(e)),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&u(n.node)}};return{run:function(){this.step()},step:function(){return s(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,d=!0,l=0,h=0,v=!1,p=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return v=u.step()&&!p,V(),!v},P=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(l=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},N=function(){v=!1,i.restart()},E=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),d=!1},L=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),p=!0,N()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),p=!0,V()},onStop:function(){u.pinNode(e,t),p=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),d&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(d=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},R=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);N()},D=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",R),o=null)},z=function(){x.on("resize",D),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){var r=Math.pow(1.4,0>t?-.2:.2);g.scale=s.scale(r,n),V(),w.fire("scale",g.scale)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",R)},B=function(){c=!1,O(),F(),x.stop("resize",D),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),E(),G(),C(),z(),c=!0),P(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},dispose:function(){B()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"}; -var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},d=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},l=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?d(e):(d=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,l()},translateRel:function(e,r){t+=e,n+=r,l()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,l()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),d=f.attr("id"),l=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&d===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&l===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i,o=1,a={},u={},s=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},f=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},c=function(){return Viva.Graph.svg("line").attr("stroke","#999")},d=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},l=function(e){e.fire("rescaled")},h={x:0,y:0},v={x:0,y:0},p={x:0,y:0},m=function(){if(e){var t="matrix("+o+", 0, 0,"+o+","+n+","+r+")";e.attr("transform",t)}},g={getNodeUI:function(e){return a[e]},getLinkUI:function(e){return u[e]},node:function(e){return"function"==typeof e?(s=e,this):void 0},link:function(e){return"function"==typeof e?(c=e,this):void 0},placeNode:function(e){return f=e,this},placeLink:function(e){return d=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,m()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(i,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(i).translate(-u.x,-u.y),f=e.getCTM().multiply(s);o=f.a,n=f.e,r=f.f;var c="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",c),l(this),o},resetScale:function(){o=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),l(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),m(),"function"==typeof i&&i(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(t,n){var r=c(t);if(r)return r.position=n,r.link=t,u[t.id]=r,e.childElementCount>0?e.insertBefore(r,e.firstChild):e.appendChild(r),r},releaseLink:function(t){var n=u[t.id];n&&(e.removeChild(n),delete u[t.id])},addNode:function(t,n){var r=s(t);if(r)return r.position=n,r.node=t,a[t.id]=r,e.appendChild(r),r},releaseNode:function(t){var n=a[t.id];n&&(e.removeChild(n),delete a[t.id])},renderNodes:function(){for(var e in a)if(a.hasOwnProperty(e)){var t=a[e];h.x=t.position.x,h.y=t.position.y,f(t,h,t.node)}},renderLinks:function(){for(var e in u)if(u.hasOwnProperty(e)){var t=u[e];v.x=t.position.from.x,v.y=t.position.from.y,p.x=t.position.to.x,p.y=t.position.to.y,d(t,v,p,t.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):i=e),t},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(g).extend(),g},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,d=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(d.x)+" "+Math.round(d.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),l=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),v=new Float32Array(h),p=new Uint32Array(h),m=0,g=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(p),v=t,p=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(l,d),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;v[n*f]=t.x,v[n*f+1]=t.y,v[n*f+2]=e.size,p[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(p,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,d=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),v=0,p=new ArrayBuffer(16*d),m=new Float32Array(p),g=new Uint32Array(p),y=function(){if((v+1)*d>p.byteLength){var e=new ArrayBuffer(2*p.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,p=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,l),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),v+=1,o=e.id},removeLink:function(e){v>0&&(v-=1),v>e.id&&v>0&&r.copyArrayPart(g,e.id*c,v*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,p,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*v),o=v-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},d=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},l=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},v=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},p=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=l(e),o={offset:e};r.textureNumber>=s.length&&d();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=l(t.offset),r=l(o);p(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],v(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){v(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,d=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),l=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,v=0,p=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(l,d),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;p[n]=t.x-e.size,p[n+1]=t.y-e.size,p[n+2]=4*e._offset,p[n+3]=t.x+e.size,p[n+4]=t.y-e.size,p[n+5]=4*e._offset+1,p[n+6]=t.x-e.size,p[n+7]=t.y+e.size,p[n+8]=4*e._offset+2,p[n+9]=t.x-e.size,p[n+10]=t.y+e.size,p[n+11]=4*e._offset+2,p[n+12]=t.x+e.size,p[n+13]=t.y-e.size,p[n+14]=4*e._offset+1,p[n+15]=t.x+e.size,p[n+16]=t.y+e.size,p[n+17]=4*e._offset+3},createNode:function(t){p=i.extendArray(p,v,c),v+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){v>0&&(v-=1),v>t.id&&v>0&&(t.src&&e.remove(t.src),i.copyArrayPart(p,t.id*c,v*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,p,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*v)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f,c=0,d=0,l=[],h=[],v={},p={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(a),g.updateTransform(a)},V=function(){a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},P=function(e){e.fire("rescaled")},N={getLinkUI:function(e){return p[e]},getNodeUI:function(e){return v[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return u=e,this},placeLink:function(e){return s=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){d>0&&m.render(),c>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(){b()},addLink:function(e,t){var n=d++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,p[e.id]=r,r},addNode:function(e,t){var n=c++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),l[n]=r,v[e.id]=r,r},translateRel:function(e,t){a[12]+=2*a[0]*e/i/a[0],a[13]-=2*a[5]*t/o/a[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=a[12],r-=a[13],a[12]+=n*(1-e),a[13]+=r*(1-e),a[0]*=e,a[5]*=e,w(),P(this),a[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var s="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(s),s}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof f&&f(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){d>0&&(d-=1);var t=p[e.id];delete p[e.id],m.removeLink(t);var n=t.id;if(d>n){if(0===d||d===n)return;var r=h[d];h[n]=r,r.id=n}},releaseNode:function(e){c>0&&(c-=1);var t=v[e.id];delete v[e.id],g.removeNode(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=l[c];l[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;c>t;++t){var n=l[t];e.x=n.position.x,e.y=-n.position.y,u&&u(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;d>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,s&&s(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):f=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-a[12])/a[0],e.y=(e.y-a[13])/a[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;c>n;++n)if(t(l[n],e.x,e.y))return l[n].node;return null}};return Viva.Graph.Utils.events(N).extend(),N},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},i=function(t){return e.getNodeAtClientPos(t,r)},o=null,a=[],u=[],s=[],f=[],c=[],d=[],l=[],h=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},p=function(e){return v(e),!1},m=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(e){var r={x:0,y:0},g=null,y=+new Date,x=function(e){m(c,[g,e]),r.x=e.clientX,r.y=e.clientY},w=function(){h.stop("mousemove",x),h.stop("mouseup",w)},V=function(){n=e.getBoundingClientRect()};window.addEventListener("resize",V),V(),e.addEventListener("mousemove",function(e){if(!o){var t,s=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,t=i(r),t&&g!==t?(g=t,s=s||m(a,[g])):null===t&&g!==t&&(s=s||m(u,[g]),g=null),s&&v(e)}}),e.addEventListener("mousedown",function(e){var o,a=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]?(a=m(s,o),h.on("mousemove",x),h.on("mouseup",w),t=window.document.onselectstart,window.document.onselectstart=p,g=o[0]):g=null,a&&v(e)}),e.addEventListener("mouseup",function(e){var o,a=+new Date;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]&&(window.document.onselectstart=t,400>a-y&&o[0]===g?m(l,o):m(d,o),y=a,m(f,o)&&v(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&l.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file +var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.1",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},P=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},N=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",P,!1):e.addEventListener("DOMMouseScroll",P,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",P,!1):e.removeEventListener("DOMMouseScroll",P,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),N(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,d=Math.sqrt(f*f+c*c);d>r&&(u.velocity.x=r*f/d,u.velocity.y=r*c/d),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};r="number"==typeof r?r:1;var o=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,r);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02,springTransform:function(){}});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),f={},c=function(e){if(e.position)return e.position;var n=(u.x1+u.x2)/2,r=(u.y1+u.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],a=o.fromId!==e.id?f[o.fromId]:f[o.toId];a&&a.location&&(n=a.location.x,r=a.location.y)}return{x:n+s.next(i)-i/2,y:r+s.next(i)-i/2}},d=function(e){return f[e]},l=function(e){f[e]=null,delete f[e]},h={},v=function(t){var n=d(t);n.mass=1+e.getLinks(t).length/3},p=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},m=function(e){return e.isPinned},g=function(t){var n=d(t);if(!n){var i=e.getNode(t);if(!i)return;n=new Viva.Graph.Physics.Body,f[t]=n;var o=c(i);n.loc(o),v(t),p(i)&&(n.isPinned=!0),r.addBody(n)}},y=function(e){g(e.id)},x=function(t){var n=d(t.id);n&&(l(t.id),r.removeBody(n),0===e.getNodesCount()&&(u.x1=u.y1=0,u.x2=u.y2=0))},w=function(e){v(e.fromId),v(e.toId);var n=d(e.fromId),i=d(e.toId),o=r.addSpring(n,i,-1,e.weight);t.springTransform(e,o),h[e.id]=o},V=function(t){var n=h[t.id];if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&v(i.id),o&&v(o.id),delete h[t.id],r.removeSpring(n)}},b=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&g(n.node.id),n.link&&w(n.link)):"remove"===n.changeType&&(n.node&&x(n.node),n.link&&V(n.link))}},P=function(){e.forEachNode(y),e.forEachLink(w),e.addEventListener("changed",b)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in f)if(f.hasOwnProperty(o)){var a=f[o];m(a)?(a.location.x=a.prevLocation.x,a.location.y=a.prevLocation.y):(a.prevLocation.x=a.location.x,a.prevLocation.y=a.location.y),t>a.location.x&&(t=a.location.x),a.location.x>r&&(r=a.location.x),n>a.location.y&&(n=a.location.y),a.location.y>i&&(i=a.location.y)}u.x1=t,u.x2=r,u.y1=n,u.y2=i}};return r.setSpringForce(o),r.setNbodyForce(i),r.setDragForce(a),P(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(20);return N(),n>e},isNodePinned:function(e){var t=d(e.id);return t?m(t):void 0},pinNode:function(e,t){var n=d(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=d(e);return t||(g(e),t=d(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=d(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",b)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a={},u=function(e){e&&(a[e.id]||(a[e.id]=i(e)),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&u(n.node)}};return{run:function(){this.step()},step:function(){return s(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,d=!0,l=0,h=0,v=!1,p=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return v=u.step()&&!p,V(),!v},P=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(l=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},N=function(){v=!1,i.restart()},E=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),d=!1},L=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),p=!0,N()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),p=!0,V()},onStop:function(){u.pinNode(e,t),p=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),d&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(d=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},R=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);N()},D=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",R),o=null)},z=function(){x.on("resize",D),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){var r=Math.pow(1.4,0>t?-.2:.2);g.scale=s.scale(r,n),V(),w.fire("scale",g.scale)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",R)},B=function(){c=!1,O(),F(),x.stop("resize",D),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),E(),G(),C(),z(),c=!0),P(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},dispose:function(){B()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t); +return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},d=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},l=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?d(e):(d=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,l()},translateRel:function(e,r){t+=e,n+=r,l()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,l()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),d=f.attr("id"),l=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&d===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&l===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i,o=1,a={},u={},s=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},f=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},c=function(){return Viva.Graph.svg("line").attr("stroke","#999")},d=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},l=function(e){e.fire("rescaled")},h={x:0,y:0},v={x:0,y:0},p={x:0,y:0},m=function(){if(e){var t="matrix("+o+", 0, 0,"+o+","+n+","+r+")";e.attr("transform",t)}},g={getNodeUI:function(e){return a[e]},getLinkUI:function(e){return u[e]},node:function(e){return"function"==typeof e?(s=e,this):void 0},link:function(e){return"function"==typeof e?(c=e,this):void 0},placeNode:function(e){return f=e,this},placeLink:function(e){return d=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,m()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(i,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(i).translate(-u.x,-u.y),f=e.getCTM().multiply(s);o=f.a,n=f.e,r=f.f;var c="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",c),l(this),o},resetScale:function(){o=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),l(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),m(),"function"==typeof i&&i(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(t,n){var r=c(t);if(r)return r.position=n,r.link=t,u[t.id]=r,e.childElementCount>0?e.insertBefore(r,e.firstChild):e.appendChild(r),r},releaseLink:function(t){var n=u[t.id];n&&(e.removeChild(n),delete u[t.id])},addNode:function(t,n){var r=s(t);if(r)return r.position=n,r.node=t,a[t.id]=r,e.appendChild(r),r},releaseNode:function(t){var n=a[t.id];n&&(e.removeChild(n),delete a[t.id])},renderNodes:function(){for(var e in a)if(a.hasOwnProperty(e)){var t=a[e];h.x=t.position.x,h.y=t.position.y,f(t,h,t.node)}},renderLinks:function(){for(var e in u)if(u.hasOwnProperty(e)){var t=u[e];v.x=t.position.from.x,v.y=t.position.from.y,p.x=t.position.to.x,p.y=t.position.to.y,d(t,v,p,t.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):i=e),t},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(g).extend(),g},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,d=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(d.x)+" "+Math.round(d.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),l=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),v=new Float32Array(h),p=new Uint32Array(h),m=0,g=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(p),v=t,p=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(l,d),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;v[n*f]=t.x,v[n*f+1]=t.y,v[n*f+2]=e.size,p[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(p,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,d=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),v=0,p=new ArrayBuffer(16*d),m=new Float32Array(p),g=new Uint32Array(p),y=function(){if((v+1)*d>p.byteLength){var e=new ArrayBuffer(2*p.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,p=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,l),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),v+=1,o=e.id},removeLink:function(e){v>0&&(v-=1),v>e.id&&v>0&&r.copyArrayPart(g,e.id*c,v*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,p,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*v),o=v-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},d=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},l=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},v=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},p=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=l(e),o={offset:e};r.textureNumber>=s.length&&d();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=l(t.offset),r=l(o);p(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],v(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){v(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,d=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),l=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,v=0,p=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(l,d),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;p[n]=t.x-e.size,p[n+1]=t.y-e.size,p[n+2]=4*e._offset,p[n+3]=t.x+e.size,p[n+4]=t.y-e.size,p[n+5]=4*e._offset+1,p[n+6]=t.x-e.size,p[n+7]=t.y+e.size,p[n+8]=4*e._offset+2,p[n+9]=t.x-e.size,p[n+10]=t.y+e.size,p[n+11]=4*e._offset+2,p[n+12]=t.x+e.size,p[n+13]=t.y-e.size,p[n+14]=4*e._offset+1,p[n+15]=t.x+e.size,p[n+16]=t.y+e.size,p[n+17]=4*e._offset+3},createNode:function(t){p=i.extendArray(p,v,c),v+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){v>0&&(v-=1),v>t.id&&v>0&&(t.src&&e.remove(t.src),i.copyArrayPart(p,t.id*c,v*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,p,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*v)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f,c=0,d=0,l=[],h=[],v={},p={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(a),g.updateTransform(a)},V=function(){a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},P=function(e){e.fire("rescaled")},N={getLinkUI:function(e){return p[e]},getNodeUI:function(e){return v[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return u=e,this},placeLink:function(e){return s=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){d>0&&m.render(),c>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(){b()},addLink:function(e,t){var n=d++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,p[e.id]=r,r},addNode:function(e,t){var n=c++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),l[n]=r,v[e.id]=r,r},translateRel:function(e,t){a[12]+=2*a[0]*e/i/a[0],a[13]-=2*a[5]*t/o/a[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=a[12],r-=a[13],a[12]+=n*(1-e),a[13]+=r*(1-e),a[0]*=e,a[5]*=e,w(),P(this),a[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var s="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(s),s}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof f&&f(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){d>0&&(d-=1);var t=p[e.id];delete p[e.id],m.removeLink(t);var n=t.id;if(d>n){if(0===d||d===n)return;var r=h[d];h[n]=r,r.id=n}},releaseNode:function(e){c>0&&(c-=1);var t=v[e.id];delete v[e.id],g.removeNode(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=l[c];l[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;c>t;++t){var n=l[t];e.x=n.position.x,e.y=-n.position.y,u&&u(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;d>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,s&&s(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):f=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-a[12])/a[0],e.y=(e.y-a[13])/a[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;c>n;++n)if(t(l[n],e.x,e.y))return l[n].node;return null}};return Viva.Graph.Utils.events(N).extend(),N},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},i=function(t){return e.getNodeAtClientPos(t,r)},o=null,a=[],u=[],s=[],f=[],c=[],d=[],l=[],h=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},p=function(e){return v(e),!1},m=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(e){var r={x:0,y:0},g=null,y=+new Date,x=function(e){m(c,[g,e]),r.x=e.clientX,r.y=e.clientY},w=function(){h.stop("mousemove",x),h.stop("mouseup",w)},V=function(){n=e.getBoundingClientRect()};window.addEventListener("resize",V),V(),e.addEventListener("mousemove",function(e){if(!o){var t,s=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,t=i(r),t&&g!==t?(g=t,s=s||m(a,[g])):null===t&&g!==t&&(s=s||m(u,[g]),g=null),s&&v(e)}}),e.addEventListener("mousedown",function(e){var o,a=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]?(a=m(s,o),h.on("mousemove",x),h.on("mouseup",w),t=window.document.onselectstart,window.document.onselectstart=p,g=o[0]):g=null,a&&v(e)}),e.addEventListener("mouseup",function(e){var o,a=+new Date;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]&&(window.document.onselectstart=t,400>a-y&&o[0]===g?m(l,o):m(d,o),y=a,m(f,o)&&v(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&l.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file diff --git a/src/Layout/forceDirected.js b/src/Layout/forceDirected.js index bdbe66d..7a9c112 100644 --- a/src/Layout/forceDirected.js +++ b/src/Layout/forceDirected.js @@ -41,7 +41,37 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { * Drag force coefficient. Used to slow down system, thus should be less than 1. * The closer it is to 0 the less tight system will be. */ - dragCoeff: 0.02 + dragCoeff: 0.02, + + /** + * Allows to transfor physical spring associated with a link. this allows clients + * to specify custom length for a link. + * + * @param {Viva.Graph.Link} link actual link for which transform is performed + * @param {Viva.Graph.Physics.Spring} spring physical spring which is associated with + * a link. Most interesting property will be 'length' + * + * @example + * // Let's say your graph represent friendship. Each link has associated + * // 'strength' of connection, distributed from 0 (not a strong connection) to + * // 1 (very strong connection) + * // + * // You want your graph to have uniformly distributed links, but stronger + * // connection should pull nodes closer: + * + * graph.addLink(user1, user2, { friendshipStrength: 0.9 }); + * var layout = Viva.Graph.Layout.forceDirected(graph, { + * springLength: 80, // 80 pixels is our ideal link length + * springTransform: function (link, spring) { + * // We can set custom desired length of a spring, based on + * // link's data: + * spring.length = 80 * (1 - link.data.friendshipStrength); + * } + * } + */ + springTransform: function (link, spring) { + // By default, it is a no-op + } }); var forceSimulator = Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()), @@ -156,6 +186,7 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { toBody = getBody(link.toId), spring = forceSimulator.addSpring(fromBody, toBody, -1.0, link.weight); + settings.springTransform(link, spring); springs[link.id] = spring; }, diff --git a/src/version.js b/src/version.js index 62c88a4..0912ce1 100644 --- a/src/version.js +++ b/src/version.js @@ -1 +1 @@ -Viva.Graph.version = '0.5.0'; +Viva.Graph.version = '0.5.1'; From b76b1574c5d4fa7cdc5197527a83c21577f5c37b Mon Sep 17 00:00:00 2001 From: Andrei Kashcha Date: Wed, 20 Nov 2013 22:30:25 -0800 Subject: [PATCH 048/276] Update customLinkLength.html --- demos/other/customLinkLength.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/demos/other/customLinkLength.html b/demos/other/customLinkLength.html index 1c0eb2e..272c102 100644 --- a/demos/other/customLinkLength.html +++ b/demos/other/customLinkLength.html @@ -27,6 +27,9 @@ springLength: idealLength, springCoeff : 0.0008, gravity : -10, + // This is the main part of this example. We are telling force directed + // layout, that we want to change length of each physical spring + // by overriding `springTransform` method: springTransform: function (link, spring) { spring.length = idealLength * (1 - link.data.connectionStrength); } From f5de1437339a69315aaa544c99985e06cff7ee93 Mon Sep 17 00:00:00 2001 From: Andrei Kashcha Date: Wed, 20 Nov 2013 22:30:41 -0800 Subject: [PATCH 049/276] Update customLinkLength.html --- demos/other/customLinkLength.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/demos/other/customLinkLength.html b/demos/other/customLinkLength.html index 6350b15..97f2e0e 100644 --- a/demos/other/customLinkLength.html +++ b/demos/other/customLinkLength.html @@ -24,6 +24,9 @@ springLength: idealLength, springCoeff : 0.0008, gravity : -10, + // This is the main part of this example. We are telling force directed + // layout, that we want to change length of each physical spring + // by overriding `springTransform` method: springTransform: function (link, spring) { spring.length = idealLength * (1 - link.data.connectionStrength); } From e7b8c4e31880d531e52c0b7b96ade5f1e36a547c Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 23 Nov 2013 17:59:25 -0800 Subject: [PATCH 050/276] Exposed integrator step --- demos/other/customLinkLength.html | 5 +++-- dist/vivagraph.js | 9 +++++++-- dist/vivagraph.min.js | 2 +- src/Layout/forceDirected.js | 9 +++++++-- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/demos/other/customLinkLength.html b/demos/other/customLinkLength.html index 6350b15..cbc8bf2 100644 --- a/demos/other/customLinkLength.html +++ b/demos/other/customLinkLength.html @@ -19,10 +19,11 @@ graph.addLink(5, 6, { connectionStrength: 0.1 }); - var idealLength = 90; + var idealLength = 100; var layout = Viva.Graph.Layout.forceDirected(graph, { springLength: idealLength, - springCoeff : 0.0008, + timeStep: 10, + springCoeff : 0.004, gravity : -10, springTransform: function (link, spring) { spring.length = idealLength * (1 - link.data.connectionStrength); diff --git a/dist/vivagraph.js b/dist/vivagraph.js index af2f8db..6346986 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -2157,7 +2157,12 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { */ springTransform: function (link, spring) { // By default, it is a no-op - } + }, + + /** + * Default time step (dt) for forces integration + */ + timeStep : 20 }); var forceSimulator = Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()), @@ -2386,7 +2391,7 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { * Performs one step of iterative layout algorithm */ step: function() { - var energy = forceSimulator.run(20); + var energy = forceSimulator.run(settings.timeStep); updateNodePositions(); return energy < STABLE_THRESHOLD; diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index d0c8406..be0b42f 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.1",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},P=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},N=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",P,!1):e.addEventListener("DOMMouseScroll",P,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",P,!1):e.removeEventListener("DOMMouseScroll",P,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),N(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,d=Math.sqrt(f*f+c*c);d>r&&(u.velocity.x=r*f/d,u.velocity.y=r*c/d),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};r="number"==typeof r?r:1;var o=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,r);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02,springTransform:function(){}});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),f={},c=function(e){if(e.position)return e.position;var n=(u.x1+u.x2)/2,r=(u.y1+u.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],a=o.fromId!==e.id?f[o.fromId]:f[o.toId];a&&a.location&&(n=a.location.x,r=a.location.y)}return{x:n+s.next(i)-i/2,y:r+s.next(i)-i/2}},d=function(e){return f[e]},l=function(e){f[e]=null,delete f[e]},h={},v=function(t){var n=d(t);n.mass=1+e.getLinks(t).length/3},p=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},m=function(e){return e.isPinned},g=function(t){var n=d(t);if(!n){var i=e.getNode(t);if(!i)return;n=new Viva.Graph.Physics.Body,f[t]=n;var o=c(i);n.loc(o),v(t),p(i)&&(n.isPinned=!0),r.addBody(n)}},y=function(e){g(e.id)},x=function(t){var n=d(t.id);n&&(l(t.id),r.removeBody(n),0===e.getNodesCount()&&(u.x1=u.y1=0,u.x2=u.y2=0))},w=function(e){v(e.fromId),v(e.toId);var n=d(e.fromId),i=d(e.toId),o=r.addSpring(n,i,-1,e.weight);t.springTransform(e,o),h[e.id]=o},V=function(t){var n=h[t.id];if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&v(i.id),o&&v(o.id),delete h[t.id],r.removeSpring(n)}},b=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&g(n.node.id),n.link&&w(n.link)):"remove"===n.changeType&&(n.node&&x(n.node),n.link&&V(n.link))}},P=function(){e.forEachNode(y),e.forEachLink(w),e.addEventListener("changed",b)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in f)if(f.hasOwnProperty(o)){var a=f[o];m(a)?(a.location.x=a.prevLocation.x,a.location.y=a.prevLocation.y):(a.prevLocation.x=a.location.x,a.prevLocation.y=a.location.y),t>a.location.x&&(t=a.location.x),a.location.x>r&&(r=a.location.x),n>a.location.y&&(n=a.location.y),a.location.y>i&&(i=a.location.y)}u.x1=t,u.x2=r,u.y1=n,u.y2=i}};return r.setSpringForce(o),r.setNbodyForce(i),r.setDragForce(a),P(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(20);return N(),n>e},isNodePinned:function(e){var t=d(e.id);return t?m(t):void 0},pinNode:function(e,t){var n=d(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=d(e);return t||(g(e),t=d(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=d(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",b)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a={},u=function(e){e&&(a[e.id]||(a[e.id]=i(e)),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&u(n.node)}};return{run:function(){this.step()},step:function(){return s(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,d=!0,l=0,h=0,v=!1,p=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return v=u.step()&&!p,V(),!v},P=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(l=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},N=function(){v=!1,i.restart()},E=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),d=!1},L=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),p=!0,N()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),p=!0,V()},onStop:function(){u.pinNode(e,t),p=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),d&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(d=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},R=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);N()},D=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",R),o=null)},z=function(){x.on("resize",D),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){var r=Math.pow(1.4,0>t?-.2:.2);g.scale=s.scale(r,n),V(),w.fire("scale",g.scale)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",R)},B=function(){c=!1,O(),F(),x.stop("resize",D),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),E(),G(),C(),z(),c=!0),P(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},dispose:function(){B()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t); +var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.1",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},P=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},N=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",P,!1):e.addEventListener("DOMMouseScroll",P,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",P,!1):e.removeEventListener("DOMMouseScroll",P,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),N(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,d=Math.sqrt(f*f+c*c);d>r&&(u.velocity.x=r*f/d,u.velocity.y=r*c/d),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};r="number"==typeof r?r:1;var o=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,r);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02,springTransform:function(){},timeStep:20});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),f={},c=function(e){if(e.position)return e.position;var n=(u.x1+u.x2)/2,r=(u.y1+u.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],a=o.fromId!==e.id?f[o.fromId]:f[o.toId];a&&a.location&&(n=a.location.x,r=a.location.y)}return{x:n+s.next(i)-i/2,y:r+s.next(i)-i/2}},d=function(e){return f[e]},l=function(e){f[e]=null,delete f[e]},h={},v=function(t){var n=d(t);n.mass=1+e.getLinks(t).length/3},p=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},m=function(e){return e.isPinned},g=function(t){var n=d(t);if(!n){var i=e.getNode(t);if(!i)return;n=new Viva.Graph.Physics.Body,f[t]=n;var o=c(i);n.loc(o),v(t),p(i)&&(n.isPinned=!0),r.addBody(n)}},y=function(e){g(e.id)},x=function(t){var n=d(t.id);n&&(l(t.id),r.removeBody(n),0===e.getNodesCount()&&(u.x1=u.y1=0,u.x2=u.y2=0))},w=function(e){v(e.fromId),v(e.toId);var n=d(e.fromId),i=d(e.toId),o=r.addSpring(n,i,-1,e.weight);t.springTransform(e,o),h[e.id]=o},V=function(t){var n=h[t.id];if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&v(i.id),o&&v(o.id),delete h[t.id],r.removeSpring(n)}},b=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&g(n.node.id),n.link&&w(n.link)):"remove"===n.changeType&&(n.node&&x(n.node),n.link&&V(n.link))}},P=function(){e.forEachNode(y),e.forEachLink(w),e.addEventListener("changed",b)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in f)if(f.hasOwnProperty(o)){var a=f[o];m(a)?(a.location.x=a.prevLocation.x,a.location.y=a.prevLocation.y):(a.prevLocation.x=a.location.x,a.prevLocation.y=a.location.y),t>a.location.x&&(t=a.location.x),a.location.x>r&&(r=a.location.x),n>a.location.y&&(n=a.location.y),a.location.y>i&&(i=a.location.y)}u.x1=t,u.x2=r,u.y1=n,u.y2=i}};return r.setSpringForce(o),r.setNbodyForce(i),r.setDragForce(a),P(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(t.timeStep);return N(),n>e},isNodePinned:function(e){var t=d(e.id);return t?m(t):void 0},pinNode:function(e,t){var n=d(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=d(e);return t||(g(e),t=d(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=d(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",b)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a={},u=function(e){e&&(a[e.id]||(a[e.id]=i(e)),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&u(n.node)}};return{run:function(){this.step()},step:function(){return s(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,d=!0,l=0,h=0,v=!1,p=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return v=u.step()&&!p,V(),!v},P=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(l=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},N=function(){v=!1,i.restart()},E=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),d=!1},L=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),p=!0,N()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),p=!0,V()},onStop:function(){u.pinNode(e,t),p=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),d&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(d=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},R=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);N()},D=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",R),o=null)},z=function(){x.on("resize",D),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){var r=Math.pow(1.4,0>t?-.2:.2);g.scale=s.scale(r,n),V(),w.fire("scale",g.scale)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",R)},B=function(){c=!1,O(),F(),x.stop("resize",D),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),E(),G(),C(),z(),c=!0),P(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},dispose:function(){B()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t); return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},d=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},l=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?d(e):(d=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,l()},translateRel:function(e,r){t+=e,n+=r,l()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,l()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),d=f.attr("id"),l=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&d===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&l===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i,o=1,a={},u={},s=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},f=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},c=function(){return Viva.Graph.svg("line").attr("stroke","#999")},d=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},l=function(e){e.fire("rescaled")},h={x:0,y:0},v={x:0,y:0},p={x:0,y:0},m=function(){if(e){var t="matrix("+o+", 0, 0,"+o+","+n+","+r+")";e.attr("transform",t)}},g={getNodeUI:function(e){return a[e]},getLinkUI:function(e){return u[e]},node:function(e){return"function"==typeof e?(s=e,this):void 0},link:function(e){return"function"==typeof e?(c=e,this):void 0},placeNode:function(e){return f=e,this},placeLink:function(e){return d=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,m()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(i,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(i).translate(-u.x,-u.y),f=e.getCTM().multiply(s);o=f.a,n=f.e,r=f.f;var c="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",c),l(this),o},resetScale:function(){o=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),l(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),m(),"function"==typeof i&&i(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(t,n){var r=c(t);if(r)return r.position=n,r.link=t,u[t.id]=r,e.childElementCount>0?e.insertBefore(r,e.firstChild):e.appendChild(r),r},releaseLink:function(t){var n=u[t.id];n&&(e.removeChild(n),delete u[t.id])},addNode:function(t,n){var r=s(t);if(r)return r.position=n,r.node=t,a[t.id]=r,e.appendChild(r),r},releaseNode:function(t){var n=a[t.id];n&&(e.removeChild(n),delete a[t.id])},renderNodes:function(){for(var e in a)if(a.hasOwnProperty(e)){var t=a[e];h.x=t.position.x,h.y=t.position.y,f(t,h,t.node)}},renderLinks:function(){for(var e in u)if(u.hasOwnProperty(e)){var t=u[e];v.x=t.position.from.x,v.y=t.position.from.y,p.x=t.position.to.x,p.y=t.position.to.y,d(t,v,p,t.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):i=e),t},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(g).extend(),g},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,d=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(d.x)+" "+Math.round(d.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),l=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),v=new Float32Array(h),p=new Uint32Array(h),m=0,g=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(p),v=t,p=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(l,d),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;v[n*f]=t.x,v[n*f+1]=t.y,v[n*f+2]=e.size,p[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(p,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,d=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),v=0,p=new ArrayBuffer(16*d),m=new Float32Array(p),g=new Uint32Array(p),y=function(){if((v+1)*d>p.byteLength){var e=new ArrayBuffer(2*p.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,p=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,l),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),v+=1,o=e.id},removeLink:function(e){v>0&&(v-=1),v>e.id&&v>0&&r.copyArrayPart(g,e.id*c,v*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,p,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*v),o=v-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},d=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},l=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},v=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},p=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=l(e),o={offset:e};r.textureNumber>=s.length&&d();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=l(t.offset),r=l(o);p(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],v(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){v(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,d=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),l=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,v=0,p=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(l,d),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;p[n]=t.x-e.size,p[n+1]=t.y-e.size,p[n+2]=4*e._offset,p[n+3]=t.x+e.size,p[n+4]=t.y-e.size,p[n+5]=4*e._offset+1,p[n+6]=t.x-e.size,p[n+7]=t.y+e.size,p[n+8]=4*e._offset+2,p[n+9]=t.x-e.size,p[n+10]=t.y+e.size,p[n+11]=4*e._offset+2,p[n+12]=t.x+e.size,p[n+13]=t.y-e.size,p[n+14]=4*e._offset+1,p[n+15]=t.x+e.size,p[n+16]=t.y+e.size,p[n+17]=4*e._offset+3},createNode:function(t){p=i.extendArray(p,v,c),v+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){v>0&&(v-=1),v>t.id&&v>0&&(t.src&&e.remove(t.src),i.copyArrayPart(p,t.id*c,v*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,p,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*v)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f,c=0,d=0,l=[],h=[],v={},p={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(a),g.updateTransform(a)},V=function(){a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},P=function(e){e.fire("rescaled")},N={getLinkUI:function(e){return p[e]},getNodeUI:function(e){return v[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return u=e,this},placeLink:function(e){return s=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){d>0&&m.render(),c>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(){b()},addLink:function(e,t){var n=d++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,p[e.id]=r,r},addNode:function(e,t){var n=c++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),l[n]=r,v[e.id]=r,r},translateRel:function(e,t){a[12]+=2*a[0]*e/i/a[0],a[13]-=2*a[5]*t/o/a[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=a[12],r-=a[13],a[12]+=n*(1-e),a[13]+=r*(1-e),a[0]*=e,a[5]*=e,w(),P(this),a[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var s="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(s),s}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof f&&f(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){d>0&&(d-=1);var t=p[e.id];delete p[e.id],m.removeLink(t);var n=t.id;if(d>n){if(0===d||d===n)return;var r=h[d];h[n]=r,r.id=n}},releaseNode:function(e){c>0&&(c-=1);var t=v[e.id];delete v[e.id],g.removeNode(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=l[c];l[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;c>t;++t){var n=l[t];e.x=n.position.x,e.y=-n.position.y,u&&u(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;d>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,s&&s(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):f=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-a[12])/a[0],e.y=(e.y-a[13])/a[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;c>n;++n)if(t(l[n],e.x,e.y))return l[n].node;return null}};return Viva.Graph.Utils.events(N).extend(),N},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},i=function(t){return e.getNodeAtClientPos(t,r)},o=null,a=[],u=[],s=[],f=[],c=[],d=[],l=[],h=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},p=function(e){return v(e),!1},m=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(e){var r={x:0,y:0},g=null,y=+new Date,x=function(e){m(c,[g,e]),r.x=e.clientX,r.y=e.clientY},w=function(){h.stop("mousemove",x),h.stop("mouseup",w)},V=function(){n=e.getBoundingClientRect()};window.addEventListener("resize",V),V(),e.addEventListener("mousemove",function(e){if(!o){var t,s=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,t=i(r),t&&g!==t?(g=t,s=s||m(a,[g])):null===t&&g!==t&&(s=s||m(u,[g]),g=null),s&&v(e)}}),e.addEventListener("mousedown",function(e){var o,a=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]?(a=m(s,o),h.on("mousemove",x),h.on("mouseup",w),t=window.document.onselectstart,window.document.onselectstart=p,g=o[0]):g=null,a&&v(e)}),e.addEventListener("mouseup",function(e){var o,a=+new Date;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]&&(window.document.onselectstart=t,400>a-y&&o[0]===g?m(l,o):m(d,o),y=a,m(f,o)&&v(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&l.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file diff --git a/src/Layout/forceDirected.js b/src/Layout/forceDirected.js index 7a9c112..20201a3 100644 --- a/src/Layout/forceDirected.js +++ b/src/Layout/forceDirected.js @@ -71,7 +71,12 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { */ springTransform: function (link, spring) { // By default, it is a no-op - } + }, + + /** + * Default time step (dt) for forces integration + */ + timeStep : 20 }); var forceSimulator = Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()), @@ -300,7 +305,7 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { * Performs one step of iterative layout algorithm */ step: function() { - var energy = forceSimulator.run(20); + var energy = forceSimulator.run(settings.timeStep); updateNodePositions(); return energy < STABLE_THRESHOLD; From 5c5bab9f4bde4617ebf97f3583cee5a601b3e50c Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 23 Nov 2013 18:00:27 -0800 Subject: [PATCH 051/276] Updated version and changelog --- CHANGELOG | 4 ++++ dist/vivagraph.js | 2 +- dist/vivagraph.min.js | 2 +- src/version.js | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index f461962..8824e7b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,7 @@ +v0.5.2 + date: Nov 23, 2013 + - Euler integrator now supports custom time step + v0.5.1 date: Nov 20, 2013 - Merged changes from v0.4.2: custom links length + fixed bug in arguments diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 6346986..a8cf7bb 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -7,7 +7,7 @@ Viva.Graph = Viva.Graph || {}; if (typeof module !== 'undefined' && module.exports) { module.exports = Viva; } -Viva.Graph.version = '0.5.1'; +Viva.Graph.version = '0.5.2'; /** * Extends target object with given fields/values in the options object. * Unlike jQuery's extend this method does not override target object diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index be0b42f..edf6cdc 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.1",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},P=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},N=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",P,!1):e.addEventListener("DOMMouseScroll",P,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",P,!1):e.removeEventListener("DOMMouseScroll",P,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),N(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,d=Math.sqrt(f*f+c*c);d>r&&(u.velocity.x=r*f/d,u.velocity.y=r*c/d),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};r="number"==typeof r?r:1;var o=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,r);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02,springTransform:function(){},timeStep:20});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),f={},c=function(e){if(e.position)return e.position;var n=(u.x1+u.x2)/2,r=(u.y1+u.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],a=o.fromId!==e.id?f[o.fromId]:f[o.toId];a&&a.location&&(n=a.location.x,r=a.location.y)}return{x:n+s.next(i)-i/2,y:r+s.next(i)-i/2}},d=function(e){return f[e]},l=function(e){f[e]=null,delete f[e]},h={},v=function(t){var n=d(t);n.mass=1+e.getLinks(t).length/3},p=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},m=function(e){return e.isPinned},g=function(t){var n=d(t);if(!n){var i=e.getNode(t);if(!i)return;n=new Viva.Graph.Physics.Body,f[t]=n;var o=c(i);n.loc(o),v(t),p(i)&&(n.isPinned=!0),r.addBody(n)}},y=function(e){g(e.id)},x=function(t){var n=d(t.id);n&&(l(t.id),r.removeBody(n),0===e.getNodesCount()&&(u.x1=u.y1=0,u.x2=u.y2=0))},w=function(e){v(e.fromId),v(e.toId);var n=d(e.fromId),i=d(e.toId),o=r.addSpring(n,i,-1,e.weight);t.springTransform(e,o),h[e.id]=o},V=function(t){var n=h[t.id];if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&v(i.id),o&&v(o.id),delete h[t.id],r.removeSpring(n)}},b=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&g(n.node.id),n.link&&w(n.link)):"remove"===n.changeType&&(n.node&&x(n.node),n.link&&V(n.link))}},P=function(){e.forEachNode(y),e.forEachLink(w),e.addEventListener("changed",b)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in f)if(f.hasOwnProperty(o)){var a=f[o];m(a)?(a.location.x=a.prevLocation.x,a.location.y=a.prevLocation.y):(a.prevLocation.x=a.location.x,a.prevLocation.y=a.location.y),t>a.location.x&&(t=a.location.x),a.location.x>r&&(r=a.location.x),n>a.location.y&&(n=a.location.y),a.location.y>i&&(i=a.location.y)}u.x1=t,u.x2=r,u.y1=n,u.y2=i}};return r.setSpringForce(o),r.setNbodyForce(i),r.setDragForce(a),P(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(t.timeStep);return N(),n>e},isNodePinned:function(e){var t=d(e.id);return t?m(t):void 0},pinNode:function(e,t){var n=d(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=d(e);return t||(g(e),t=d(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=d(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",b)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a={},u=function(e){e&&(a[e.id]||(a[e.id]=i(e)),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&u(n.node)}};return{run:function(){this.step()},step:function(){return s(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,d=!0,l=0,h=0,v=!1,p=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return v=u.step()&&!p,V(),!v},P=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(l=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},N=function(){v=!1,i.restart()},E=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),d=!1},L=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),p=!0,N()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),p=!0,V()},onStop:function(){u.pinNode(e,t),p=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),d&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(d=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},R=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);N()},D=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",R),o=null)},z=function(){x.on("resize",D),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){var r=Math.pow(1.4,0>t?-.2:.2);g.scale=s.scale(r,n),V(),w.fire("scale",g.scale)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",R)},B=function(){c=!1,O(),F(),x.stop("resize",D),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),E(),G(),C(),z(),c=!0),P(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},dispose:function(){B()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t); +var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.2",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},P=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},N=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",P,!1):e.addEventListener("DOMMouseScroll",P,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",P,!1):e.removeEventListener("DOMMouseScroll",P,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),N(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,d=Math.sqrt(f*f+c*c);d>r&&(u.velocity.x=r*f/d,u.velocity.y=r*c/d),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};r="number"==typeof r?r:1;var o=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,r);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02,springTransform:function(){},timeStep:20});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),f={},c=function(e){if(e.position)return e.position;var n=(u.x1+u.x2)/2,r=(u.y1+u.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],a=o.fromId!==e.id?f[o.fromId]:f[o.toId];a&&a.location&&(n=a.location.x,r=a.location.y)}return{x:n+s.next(i)-i/2,y:r+s.next(i)-i/2}},d=function(e){return f[e]},l=function(e){f[e]=null,delete f[e]},h={},v=function(t){var n=d(t);n.mass=1+e.getLinks(t).length/3},p=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},m=function(e){return e.isPinned},g=function(t){var n=d(t);if(!n){var i=e.getNode(t);if(!i)return;n=new Viva.Graph.Physics.Body,f[t]=n;var o=c(i);n.loc(o),v(t),p(i)&&(n.isPinned=!0),r.addBody(n)}},y=function(e){g(e.id)},x=function(t){var n=d(t.id);n&&(l(t.id),r.removeBody(n),0===e.getNodesCount()&&(u.x1=u.y1=0,u.x2=u.y2=0))},w=function(e){v(e.fromId),v(e.toId);var n=d(e.fromId),i=d(e.toId),o=r.addSpring(n,i,-1,e.weight);t.springTransform(e,o),h[e.id]=o},V=function(t){var n=h[t.id];if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&v(i.id),o&&v(o.id),delete h[t.id],r.removeSpring(n)}},b=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&g(n.node.id),n.link&&w(n.link)):"remove"===n.changeType&&(n.node&&x(n.node),n.link&&V(n.link))}},P=function(){e.forEachNode(y),e.forEachLink(w),e.addEventListener("changed",b)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in f)if(f.hasOwnProperty(o)){var a=f[o];m(a)?(a.location.x=a.prevLocation.x,a.location.y=a.prevLocation.y):(a.prevLocation.x=a.location.x,a.prevLocation.y=a.location.y),t>a.location.x&&(t=a.location.x),a.location.x>r&&(r=a.location.x),n>a.location.y&&(n=a.location.y),a.location.y>i&&(i=a.location.y)}u.x1=t,u.x2=r,u.y1=n,u.y2=i}};return r.setSpringForce(o),r.setNbodyForce(i),r.setDragForce(a),P(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(t.timeStep);return N(),n>e},isNodePinned:function(e){var t=d(e.id);return t?m(t):void 0},pinNode:function(e,t){var n=d(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=d(e);return t||(g(e),t=d(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=d(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",b)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a={},u=function(e){e&&(a[e.id]||(a[e.id]=i(e)),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&u(n.node)}};return{run:function(){this.step()},step:function(){return s(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,d=!0,l=0,h=0,v=!1,p=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return v=u.step()&&!p,V(),!v},P=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(l=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},N=function(){v=!1,i.restart()},E=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),d=!1},L=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),p=!0,N()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),p=!0,V()},onStop:function(){u.pinNode(e,t),p=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),d&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(d=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},R=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);N()},D=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",R),o=null)},z=function(){x.on("resize",D),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){var r=Math.pow(1.4,0>t?-.2:.2);g.scale=s.scale(r,n),V(),w.fire("scale",g.scale)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",R)},B=function(){c=!1,O(),F(),x.stop("resize",D),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),E(),G(),C(),z(),c=!0),P(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},dispose:function(){B()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t); return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},d=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},l=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?d(e):(d=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,l()},translateRel:function(e,r){t+=e,n+=r,l()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,l()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),d=f.attr("id"),l=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&d===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&l===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i,o=1,a={},u={},s=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},f=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},c=function(){return Viva.Graph.svg("line").attr("stroke","#999")},d=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},l=function(e){e.fire("rescaled")},h={x:0,y:0},v={x:0,y:0},p={x:0,y:0},m=function(){if(e){var t="matrix("+o+", 0, 0,"+o+","+n+","+r+")";e.attr("transform",t)}},g={getNodeUI:function(e){return a[e]},getLinkUI:function(e){return u[e]},node:function(e){return"function"==typeof e?(s=e,this):void 0},link:function(e){return"function"==typeof e?(c=e,this):void 0},placeNode:function(e){return f=e,this},placeLink:function(e){return d=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,m()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(i,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(i).translate(-u.x,-u.y),f=e.getCTM().multiply(s);o=f.a,n=f.e,r=f.f;var c="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",c),l(this),o},resetScale:function(){o=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),l(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),m(),"function"==typeof i&&i(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(t,n){var r=c(t);if(r)return r.position=n,r.link=t,u[t.id]=r,e.childElementCount>0?e.insertBefore(r,e.firstChild):e.appendChild(r),r},releaseLink:function(t){var n=u[t.id];n&&(e.removeChild(n),delete u[t.id])},addNode:function(t,n){var r=s(t);if(r)return r.position=n,r.node=t,a[t.id]=r,e.appendChild(r),r},releaseNode:function(t){var n=a[t.id];n&&(e.removeChild(n),delete a[t.id])},renderNodes:function(){for(var e in a)if(a.hasOwnProperty(e)){var t=a[e];h.x=t.position.x,h.y=t.position.y,f(t,h,t.node)}},renderLinks:function(){for(var e in u)if(u.hasOwnProperty(e)){var t=u[e];v.x=t.position.from.x,v.y=t.position.from.y,p.x=t.position.to.x,p.y=t.position.to.y,d(t,v,p,t.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):i=e),t},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(g).extend(),g},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,d=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(d.x)+" "+Math.round(d.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),l=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),v=new Float32Array(h),p=new Uint32Array(h),m=0,g=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(p),v=t,p=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(l,d),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;v[n*f]=t.x,v[n*f+1]=t.y,v[n*f+2]=e.size,p[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(p,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,d=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),v=0,p=new ArrayBuffer(16*d),m=new Float32Array(p),g=new Uint32Array(p),y=function(){if((v+1)*d>p.byteLength){var e=new ArrayBuffer(2*p.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,p=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,l),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),v+=1,o=e.id},removeLink:function(e){v>0&&(v-=1),v>e.id&&v>0&&r.copyArrayPart(g,e.id*c,v*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,p,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*v),o=v-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},d=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},l=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},v=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},p=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=l(e),o={offset:e};r.textureNumber>=s.length&&d();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=l(t.offset),r=l(o);p(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],v(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){v(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,d=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),l=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,v=0,p=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(l,d),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;p[n]=t.x-e.size,p[n+1]=t.y-e.size,p[n+2]=4*e._offset,p[n+3]=t.x+e.size,p[n+4]=t.y-e.size,p[n+5]=4*e._offset+1,p[n+6]=t.x-e.size,p[n+7]=t.y+e.size,p[n+8]=4*e._offset+2,p[n+9]=t.x-e.size,p[n+10]=t.y+e.size,p[n+11]=4*e._offset+2,p[n+12]=t.x+e.size,p[n+13]=t.y-e.size,p[n+14]=4*e._offset+1,p[n+15]=t.x+e.size,p[n+16]=t.y+e.size,p[n+17]=4*e._offset+3},createNode:function(t){p=i.extendArray(p,v,c),v+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){v>0&&(v-=1),v>t.id&&v>0&&(t.src&&e.remove(t.src),i.copyArrayPart(p,t.id*c,v*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,p,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*v)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f,c=0,d=0,l=[],h=[],v={},p={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(a),g.updateTransform(a)},V=function(){a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},P=function(e){e.fire("rescaled")},N={getLinkUI:function(e){return p[e]},getNodeUI:function(e){return v[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return u=e,this},placeLink:function(e){return s=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){d>0&&m.render(),c>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(){b()},addLink:function(e,t){var n=d++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,p[e.id]=r,r},addNode:function(e,t){var n=c++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),l[n]=r,v[e.id]=r,r},translateRel:function(e,t){a[12]+=2*a[0]*e/i/a[0],a[13]-=2*a[5]*t/o/a[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=a[12],r-=a[13],a[12]+=n*(1-e),a[13]+=r*(1-e),a[0]*=e,a[5]*=e,w(),P(this),a[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var s="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(s),s}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof f&&f(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){d>0&&(d-=1);var t=p[e.id];delete p[e.id],m.removeLink(t);var n=t.id;if(d>n){if(0===d||d===n)return;var r=h[d];h[n]=r,r.id=n}},releaseNode:function(e){c>0&&(c-=1);var t=v[e.id];delete v[e.id],g.removeNode(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=l[c];l[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;c>t;++t){var n=l[t];e.x=n.position.x,e.y=-n.position.y,u&&u(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;d>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,s&&s(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):f=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-a[12])/a[0],e.y=(e.y-a[13])/a[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;c>n;++n)if(t(l[n],e.x,e.y))return l[n].node;return null}};return Viva.Graph.Utils.events(N).extend(),N},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},i=function(t){return e.getNodeAtClientPos(t,r)},o=null,a=[],u=[],s=[],f=[],c=[],d=[],l=[],h=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},p=function(e){return v(e),!1},m=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(e){var r={x:0,y:0},g=null,y=+new Date,x=function(e){m(c,[g,e]),r.x=e.clientX,r.y=e.clientY},w=function(){h.stop("mousemove",x),h.stop("mouseup",w)},V=function(){n=e.getBoundingClientRect()};window.addEventListener("resize",V),V(),e.addEventListener("mousemove",function(e){if(!o){var t,s=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,t=i(r),t&&g!==t?(g=t,s=s||m(a,[g])):null===t&&g!==t&&(s=s||m(u,[g]),g=null),s&&v(e)}}),e.addEventListener("mousedown",function(e){var o,a=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]?(a=m(s,o),h.on("mousemove",x),h.on("mouseup",w),t=window.document.onselectstart,window.document.onselectstart=p,g=o[0]):g=null,a&&v(e)}),e.addEventListener("mouseup",function(e){var o,a=+new Date;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]&&(window.document.onselectstart=t,400>a-y&&o[0]===g?m(l,o):m(d,o),y=a,m(f,o)&&v(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&l.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file diff --git a/src/version.js b/src/version.js index 0912ce1..4c3129a 100644 --- a/src/version.js +++ b/src/version.js @@ -1 +1 @@ -Viva.Graph.version = '0.5.1'; +Viva.Graph.version = '0.5.2'; From fe9cdfe9c9bba71e02ef6ddf6894daa54d4d113c Mon Sep 17 00:00:00 2001 From: anvaka Date: Thu, 12 Dec 2013 21:40:38 -0800 Subject: [PATCH 052/276] Added migration guide for 0.4 -> 0.5 --- docs/upgrade_guide.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 docs/upgrade_guide.md diff --git a/docs/upgrade_guide.md b/docs/upgrade_guide.md new file mode 100644 index 0000000..28233d7 --- /dev/null +++ b/docs/upgrade_guide.md @@ -0,0 +1,4 @@ +# This is a migration guide for upcoming versions of vivagraph + +## 0.4.x -> 0.5.x + From e0fd42b30b6f2d5158cee43710af7fb4b3003725 Mon Sep 17 00:00:00 2001 From: Andrei Kashcha Date: Thu, 12 Dec 2013 23:19:18 -0800 Subject: [PATCH 053/276] Update upgrade_guide.md --- docs/upgrade_guide.md | 84 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 2 deletions(-) diff --git a/docs/upgrade_guide.md b/docs/upgrade_guide.md index 28233d7..b037439 100644 --- a/docs/upgrade_guide.md +++ b/docs/upgrade_guide.md @@ -1,4 +1,84 @@ -# This is a migration guide for upcoming versions of vivagraph +Migrating from 0.4 to 0.5 +------------------------- -## 0.4.x -> 0.5.x +Main reason for breaking changes below is that v.0.4 does not allow to render the same graph by multiple renderers. Please feel free to email me and ask for help, if you find this migration guide not sufficient. +## node.position + +`position` attribute is moved out from the node object into layout provider. + +**Why?** Having shared node `position` makes impossible rendering of the same graph by two different layouters. + +_v.0.4.*_ +``` js + // each node object has "position" on it: + graph.forEachNode(function (node) { + var position = node.position; + position.x += 1; // move by one pixel + }); +``` + +_v.0.5.*_ +``` js + // "position" is now part of layouter: + graph.forEachNode(function (node) { + // layout here is instance of Viva.Graph.Layout.forceDirected or Viva.Graph.Layout.constant: + var position = layout.getNodePosition(node.id); + position.x += 1; + }); +``` + +To give initial positions to nodes in v.0.5.* simply call: `layout.setNodePosition(node, x, y)`. + +## node.ui + +`ui` attribute is moved out from the node/link objects into graphics provider. + +**Why?** having shared `ui` attribute makes impossible rendering of the same graph by multiple renderers. + +_v.0.4.*_ +``` js + // each node object has "position" on it: + graph.forEachNode(function (node) { + console.log(node.ui); + }); + + // each link object has "position" on it: + graph.forEachLink(function (link) { + console.log(link.ui); + }); +``` + +_v.0.5.*_ +``` js + // "position" is now part of layouter: + graph.forEachNode(function (node) { + // graphics here can be instance of Viva.Graph.View.svgGraphics or Viva.Graph.View.webglGraphics: + console.dir(graphics.getNodeUI(node.id)); + }); + // "position" is now part of layouter: + graph.forEachLink(function (link) { + // graphics here can be instance of Viva.Graph.View.svgGraphics or Viva.Graph.View.webglGraphics: + console.dir(graphics.getLinkUI(link.id)); + }); +``` + +## node.isPinned + +`node.isPinned` is no longer used to determine whether node is pinned or not. This responsibility is moved to layouter. + +**Why?** Same reasons as above. Disabling node movement in one renderer should not affect movement of the same node in other renderers. + +_v.0.4.*_ +``` js +// toggle node pinning: +node.data.isPinned = !node.data.isPinned; +``` + +_v.0.5.*_ +``` js +// toggle node pinning: +var wasPinned = layout.isNodePinned(node); +layout.pinNode(node, !wasPinned); +// layout here is instance of Viva.Graph.Layout.forceDirected or Viva.Graph.Layout.constant. +``` From 97af7ed59f446f6814b475194beb92e2fda69871 Mon Sep 17 00:00:00 2001 From: Andrei Kashcha Date: Fri, 13 Dec 2013 00:06:42 -0800 Subject: [PATCH 054/276] Update upgrade_guide.md --- docs/upgrade_guide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/upgrade_guide.md b/docs/upgrade_guide.md index b037439..c10e1d7 100644 --- a/docs/upgrade_guide.md +++ b/docs/upgrade_guide.md @@ -51,12 +51,12 @@ _v.0.4.*_ _v.0.5.*_ ``` js - // "position" is now part of layouter: + // "ui" is now part of graphics: graph.forEachNode(function (node) { // graphics here can be instance of Viva.Graph.View.svgGraphics or Viva.Graph.View.webglGraphics: console.dir(graphics.getNodeUI(node.id)); }); - // "position" is now part of layouter: + // "ui" is now part of graphics: graph.forEachLink(function (link) { // graphics here can be instance of Viva.Graph.View.svgGraphics or Viva.Graph.View.webglGraphics: console.dir(graphics.getLinkUI(link.id)); From ecf9cdb4cabfb8add20e3e12c67e540c9c1d1b99 Mon Sep 17 00:00:00 2001 From: Andrei Kashcha Date: Fri, 13 Dec 2013 00:09:16 -0800 Subject: [PATCH 055/276] Added link to upgrade guide --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 65dbc33..a9f0e3d 100644 --- a/README.md +++ b/README.md @@ -166,6 +166,11 @@ grunt ``` The combined/minified code should be stored in ```dist``` folder. +Upgrade guide +------------- + +Please refer the [upgrade guide](https://github.com/anvaka/VivaGraphJS/blob/master/docs/upgrade_guide.md) to see how to update older versions of the library to the latest one. + I need your feedback ---------------------------------------------------- @@ -176,4 +181,4 @@ Though I implemented this library from scratch, I went through many existing lib * [Dracula Graph Library](https://github.com/strathausen/dracula) - written by [Johann Philipp Strathausen](https://github.com/strathausen) and uses [Raphaël](http://raphaeljs.com/) library to render graphs. Has very simple API. * [D3](http://mbostock.github.com/d3/ex/force.html) - one of the best data visualization library in JavaScript world. From [Mike Bostock](https://github.com/mbostock). -My goal is to create highly performant javascript library, which serves in the field of graph drawing. To certain extent I achieved it. But I have no doubt there is much more to improve here. \ No newline at end of file +My goal is to create highly performant javascript library, which serves in the field of graph drawing. To certain extent I achieved it. But I have no doubt there is much more to improve here. From 7f8186391c7e7397c3b34fb8976cce5635de038a Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 14 Dec 2013 01:07:10 -0800 Subject: [PATCH 056/276] Naive approach to zooming This will be changed. --- demos/other/zoomPanAPI.html | 57 +++++++++++++++++++++++++++++++++++++ dist/vivagraph.js | 32 +++++++++++++++++---- dist/vivagraph.min.js | 4 +-- src/View/renderer.js | 30 +++++++++++++++---- 4 files changed, 110 insertions(+), 13 deletions(-) create mode 100644 demos/other/zoomPanAPI.html diff --git a/demos/other/zoomPanAPI.html b/demos/other/zoomPanAPI.html new file mode 100644 index 0000000..cf6de53 --- /dev/null +++ b/demos/other/zoomPanAPI.html @@ -0,0 +1,57 @@ + + + + VivaGraphs test page + + + + + + +
+ Zoom In | Zoom Out
+ Reset +
+ + + diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 01038c9..ce59d6f 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -2186,7 +2186,7 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { // account all neighbouring nodes/links, not only one. // How about center of mass? if (node.position) { - return node.position; + return node.position; } var baseX = (graphRect.x1 + graphRect.x2) / 2, baseY = (graphRect.y1 + graphRect.y2) / 2, @@ -3027,6 +3027,22 @@ Viva.Graph.View.renderer = function (graph, settings) { } }, + scale = function (out, scrollPoint) { + if (!scrollPoint) { + var containerSize = Viva.Graph.Utils.getDimension(container); + scrollPoint = { + x: containerSize.width/2, + y: containerSize.height/2 + }; + } + scrollPoint = scrollPoint || {}; + var scaleFactor = Math.pow(1 + 0.4, out ? -0.2 : 0.2); + transform.scale = graphics.scale(scaleFactor, scrollPoint); + + renderGraph(); + publicEvents.fire('scale', transform.scale); + }, + listenToEvents = function () { windowEvents.on('resize', onWindowResized); @@ -3041,11 +3057,7 @@ Viva.Graph.View.renderer = function (graph, settings) { }); containerDrag.onScroll(function (e, scaleOffset, scrollPoint) { - var scaleFactor = Math.pow(1 + 0.4, scaleOffset < 0 ? -0.2 : 0.2); - transform.scale = graphics.scale(scaleFactor, scrollPoint); - - renderGraph(); - publicEvents.fire('scale', transform.scale); + scale(scaleOffset < 0, scrollPoint); }); graph.forEachNode(listenNodeEvents); @@ -3123,6 +3135,14 @@ Viva.Graph.View.renderer = function (graph, settings) { return this; }, + zoomOut: function () { + scale(true); + }, + + zoomIn: function () { + scale(false); + }, + /** * Removes this renderer and deallocates all resources/timers */ diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index edf6cdc..1cfa01d 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.2",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},P=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},N=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",P,!1):e.addEventListener("DOMMouseScroll",P,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",P,!1):e.removeEventListener("DOMMouseScroll",P,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),N(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,d=Math.sqrt(f*f+c*c);d>r&&(u.velocity.x=r*f/d,u.velocity.y=r*c/d),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};r="number"==typeof r?r:1;var o=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,r);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02,springTransform:function(){},timeStep:20});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),f={},c=function(e){if(e.position)return e.position;var n=(u.x1+u.x2)/2,r=(u.y1+u.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],a=o.fromId!==e.id?f[o.fromId]:f[o.toId];a&&a.location&&(n=a.location.x,r=a.location.y)}return{x:n+s.next(i)-i/2,y:r+s.next(i)-i/2}},d=function(e){return f[e]},l=function(e){f[e]=null,delete f[e]},h={},v=function(t){var n=d(t);n.mass=1+e.getLinks(t).length/3},p=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},m=function(e){return e.isPinned},g=function(t){var n=d(t);if(!n){var i=e.getNode(t);if(!i)return;n=new Viva.Graph.Physics.Body,f[t]=n;var o=c(i);n.loc(o),v(t),p(i)&&(n.isPinned=!0),r.addBody(n)}},y=function(e){g(e.id)},x=function(t){var n=d(t.id);n&&(l(t.id),r.removeBody(n),0===e.getNodesCount()&&(u.x1=u.y1=0,u.x2=u.y2=0))},w=function(e){v(e.fromId),v(e.toId);var n=d(e.fromId),i=d(e.toId),o=r.addSpring(n,i,-1,e.weight);t.springTransform(e,o),h[e.id]=o},V=function(t){var n=h[t.id];if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&v(i.id),o&&v(o.id),delete h[t.id],r.removeSpring(n)}},b=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&g(n.node.id),n.link&&w(n.link)):"remove"===n.changeType&&(n.node&&x(n.node),n.link&&V(n.link))}},P=function(){e.forEachNode(y),e.forEachLink(w),e.addEventListener("changed",b)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in f)if(f.hasOwnProperty(o)){var a=f[o];m(a)?(a.location.x=a.prevLocation.x,a.location.y=a.prevLocation.y):(a.prevLocation.x=a.location.x,a.prevLocation.y=a.location.y),t>a.location.x&&(t=a.location.x),a.location.x>r&&(r=a.location.x),n>a.location.y&&(n=a.location.y),a.location.y>i&&(i=a.location.y)}u.x1=t,u.x2=r,u.y1=n,u.y2=i}};return r.setSpringForce(o),r.setNbodyForce(i),r.setDragForce(a),P(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(t.timeStep);return N(),n>e},isNodePinned:function(e){var t=d(e.id);return t?m(t):void 0},pinNode:function(e,t){var n=d(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=d(e);return t||(g(e),t=d(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=d(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",b)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a={},u=function(e){e&&(a[e.id]||(a[e.id]=i(e)),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&u(n.node)}};return{run:function(){this.step()},step:function(){return s(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,d=!0,l=0,h=0,v=!1,p=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return v=u.step()&&!p,V(),!v},P=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(l=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},N=function(){v=!1,i.restart()},E=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),d=!1},L=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),p=!0,N()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),p=!0,V()},onStop:function(){u.pinNode(e,t),p=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),d&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(d=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},R=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);N()},D=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",R),o=null)},z=function(){x.on("resize",D),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){var r=Math.pow(1.4,0>t?-.2:.2);g.scale=s.scale(r,n),V(),w.fire("scale",g.scale)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",R)},B=function(){c=!1,O(),F(),x.stop("resize",D),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),E(),G(),C(),z(),c=!0),P(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},dispose:function(){B()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t); -return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},d=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},l=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?d(e):(d=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,l()},translateRel:function(e,r){t+=e,n+=r,l()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,l()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),d=f.attr("id"),l=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&d===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&l===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i,o=1,a={},u={},s=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},f=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},c=function(){return Viva.Graph.svg("line").attr("stroke","#999")},d=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},l=function(e){e.fire("rescaled")},h={x:0,y:0},v={x:0,y:0},p={x:0,y:0},m=function(){if(e){var t="matrix("+o+", 0, 0,"+o+","+n+","+r+")";e.attr("transform",t)}},g={getNodeUI:function(e){return a[e]},getLinkUI:function(e){return u[e]},node:function(e){return"function"==typeof e?(s=e,this):void 0},link:function(e){return"function"==typeof e?(c=e,this):void 0},placeNode:function(e){return f=e,this},placeLink:function(e){return d=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,m()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(i,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(i).translate(-u.x,-u.y),f=e.getCTM().multiply(s);o=f.a,n=f.e,r=f.f;var c="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",c),l(this),o},resetScale:function(){o=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),l(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),m(),"function"==typeof i&&i(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(t,n){var r=c(t);if(r)return r.position=n,r.link=t,u[t.id]=r,e.childElementCount>0?e.insertBefore(r,e.firstChild):e.appendChild(r),r},releaseLink:function(t){var n=u[t.id];n&&(e.removeChild(n),delete u[t.id])},addNode:function(t,n){var r=s(t);if(r)return r.position=n,r.node=t,a[t.id]=r,e.appendChild(r),r},releaseNode:function(t){var n=a[t.id];n&&(e.removeChild(n),delete a[t.id])},renderNodes:function(){for(var e in a)if(a.hasOwnProperty(e)){var t=a[e];h.x=t.position.x,h.y=t.position.y,f(t,h,t.node)}},renderLinks:function(){for(var e in u)if(u.hasOwnProperty(e)){var t=u[e];v.x=t.position.from.x,v.y=t.position.from.y,p.x=t.position.to.x,p.y=t.position.to.y,d(t,v,p,t.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):i=e),t},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(g).extend(),g},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,d=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(d.x)+" "+Math.round(d.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),l=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),v=new Float32Array(h),p=new Uint32Array(h),m=0,g=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(p),v=t,p=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(l,d),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;v[n*f]=t.x,v[n*f+1]=t.y,v[n*f+2]=e.size,p[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(p,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,d=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),v=0,p=new ArrayBuffer(16*d),m=new Float32Array(p),g=new Uint32Array(p),y=function(){if((v+1)*d>p.byteLength){var e=new ArrayBuffer(2*p.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,p=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,l),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),v+=1,o=e.id},removeLink:function(e){v>0&&(v-=1),v>e.id&&v>0&&r.copyArrayPart(g,e.id*c,v*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,p,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*v),o=v-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},d=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},l=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},v=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},p=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=l(e),o={offset:e};r.textureNumber>=s.length&&d();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=l(t.offset),r=l(o);p(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],v(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){v(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,d=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),l=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,v=0,p=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(l,d),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;p[n]=t.x-e.size,p[n+1]=t.y-e.size,p[n+2]=4*e._offset,p[n+3]=t.x+e.size,p[n+4]=t.y-e.size,p[n+5]=4*e._offset+1,p[n+6]=t.x-e.size,p[n+7]=t.y+e.size,p[n+8]=4*e._offset+2,p[n+9]=t.x-e.size,p[n+10]=t.y+e.size,p[n+11]=4*e._offset+2,p[n+12]=t.x+e.size,p[n+13]=t.y-e.size,p[n+14]=4*e._offset+1,p[n+15]=t.x+e.size,p[n+16]=t.y+e.size,p[n+17]=4*e._offset+3},createNode:function(t){p=i.extendArray(p,v,c),v+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){v>0&&(v-=1),v>t.id&&v>0&&(t.src&&e.remove(t.src),i.copyArrayPart(p,t.id*c,v*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,p,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*v)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f,c=0,d=0,l=[],h=[],v={},p={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(a),g.updateTransform(a)},V=function(){a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},P=function(e){e.fire("rescaled")},N={getLinkUI:function(e){return p[e]},getNodeUI:function(e){return v[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return u=e,this},placeLink:function(e){return s=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){d>0&&m.render(),c>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(){b()},addLink:function(e,t){var n=d++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,p[e.id]=r,r},addNode:function(e,t){var n=c++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),l[n]=r,v[e.id]=r,r},translateRel:function(e,t){a[12]+=2*a[0]*e/i/a[0],a[13]-=2*a[5]*t/o/a[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=a[12],r-=a[13],a[12]+=n*(1-e),a[13]+=r*(1-e),a[0]*=e,a[5]*=e,w(),P(this),a[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var s="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(s),s}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof f&&f(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){d>0&&(d-=1);var t=p[e.id];delete p[e.id],m.removeLink(t);var n=t.id;if(d>n){if(0===d||d===n)return;var r=h[d];h[n]=r,r.id=n}},releaseNode:function(e){c>0&&(c-=1);var t=v[e.id];delete v[e.id],g.removeNode(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=l[c];l[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;c>t;++t){var n=l[t];e.x=n.position.x,e.y=-n.position.y,u&&u(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;d>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,s&&s(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):f=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-a[12])/a[0],e.y=(e.y-a[13])/a[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;c>n;++n)if(t(l[n],e.x,e.y))return l[n].node;return null}};return Viva.Graph.Utils.events(N).extend(),N},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},i=function(t){return e.getNodeAtClientPos(t,r)},o=null,a=[],u=[],s=[],f=[],c=[],d=[],l=[],h=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},p=function(e){return v(e),!1},m=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(e){var r={x:0,y:0},g=null,y=+new Date,x=function(e){m(c,[g,e]),r.x=e.clientX,r.y=e.clientY},w=function(){h.stop("mousemove",x),h.stop("mouseup",w)},V=function(){n=e.getBoundingClientRect()};window.addEventListener("resize",V),V(),e.addEventListener("mousemove",function(e){if(!o){var t,s=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,t=i(r),t&&g!==t?(g=t,s=s||m(a,[g])):null===t&&g!==t&&(s=s||m(u,[g]),g=null),s&&v(e)}}),e.addEventListener("mousedown",function(e){var o,a=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]?(a=m(s,o),h.on("mousemove",x),h.on("mouseup",w),t=window.document.onselectstart,window.document.onselectstart=p,g=o[0]):g=null,a&&v(e)}),e.addEventListener("mouseup",function(e){var o,a=+new Date;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]&&(window.document.onselectstart=t,400>a-y&&o[0]===g?m(l,o):m(d,o),y=a,m(f,o)&&v(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&l.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file +var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.2",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},P=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},N=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",P,!1):e.addEventListener("DOMMouseScroll",P,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",P,!1):e.removeEventListener("DOMMouseScroll",P,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),N(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,d=Math.sqrt(f*f+c*c);d>r&&(u.velocity.x=r*f/d,u.velocity.y=r*c/d),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};r="number"==typeof r?r:1;var o=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,r);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02,springTransform:function(){},timeStep:20});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),f={},c=function(e){if(e.position)return e.position;var n=(u.x1+u.x2)/2,r=(u.y1+u.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],a=o.fromId!==e.id?f[o.fromId]:f[o.toId];a&&a.location&&(n=a.location.x,r=a.location.y)}return{x:n+s.next(i)-i/2,y:r+s.next(i)-i/2}},d=function(e){return f[e]},l=function(e){f[e]=null,delete f[e]},h={},v=function(t){var n=d(t);n.mass=1+e.getLinks(t).length/3},p=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},m=function(e){return e.isPinned},g=function(t){var n=d(t);if(!n){var i=e.getNode(t);if(!i)return;n=new Viva.Graph.Physics.Body,f[t]=n;var o=c(i);n.loc(o),v(t),p(i)&&(n.isPinned=!0),r.addBody(n)}},y=function(e){g(e.id)},x=function(t){var n=d(t.id);n&&(l(t.id),r.removeBody(n),0===e.getNodesCount()&&(u.x1=u.y1=0,u.x2=u.y2=0))},w=function(e){v(e.fromId),v(e.toId);var n=d(e.fromId),i=d(e.toId),o=r.addSpring(n,i,-1,e.weight);t.springTransform(e,o),h[e.id]=o},V=function(t){var n=h[t.id];if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&v(i.id),o&&v(o.id),delete h[t.id],r.removeSpring(n)}},b=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&g(n.node.id),n.link&&w(n.link)):"remove"===n.changeType&&(n.node&&x(n.node),n.link&&V(n.link))}},P=function(){e.forEachNode(y),e.forEachLink(w),e.addEventListener("changed",b)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in f)if(f.hasOwnProperty(o)){var a=f[o];m(a)?(a.location.x=a.prevLocation.x,a.location.y=a.prevLocation.y):(a.prevLocation.x=a.location.x,a.prevLocation.y=a.location.y),t>a.location.x&&(t=a.location.x),a.location.x>r&&(r=a.location.x),n>a.location.y&&(n=a.location.y),a.location.y>i&&(i=a.location.y)}u.x1=t,u.x2=r,u.y1=n,u.y2=i}};return r.setSpringForce(o),r.setNbodyForce(i),r.setDragForce(a),P(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(t.timeStep);return N(),n>e},isNodePinned:function(e){var t=d(e.id);return t?m(t):void 0},pinNode:function(e,t){var n=d(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=d(e);return t||(g(e),t=d(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=d(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",b)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a={},u=function(e){e&&(a[e.id]||(a[e.id]=i(e)),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&u(n.node)}};return{run:function(){this.step()},step:function(){return s(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,d=!0,l=0,h=0,v=!1,p=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return v=u.step()&&!p,V(),!v},P=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(l=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},N=function(){v=!1,i.restart()},E=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),d=!1},L=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),p=!0,N()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),p=!0,V()},onStop:function(){u.pinNode(e,t),p=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),d&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(d=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},D=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);N()},R=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",D),o=null)},z=function(e,t){if(!t){var n=Viva.Graph.Utils.getDimension(f);t={x:n.width/2,y:n.height/2}}t=t||{};var r=Math.pow(1.4,e?-.2:.2);g.scale=s.scale(r,t),V(),w.fire("scale",g.scale)},B=function(){x.on("resize",R),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){z(0>t,n)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",D)},Y=function(){c=!1,O(),F(),x.stop("resize",R),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),E(),G(),C(),B(),c=!0),P(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},zoomOut:function(){z(!0)},zoomIn:function(){z(!1)},dispose:function(){Y()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e) +}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},d=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},l=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?d(e):(d=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,l()},translateRel:function(e,r){t+=e,n+=r,l()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,l()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),d=f.attr("id"),l=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&d===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&l===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i,o=1,a={},u={},s=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},f=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},c=function(){return Viva.Graph.svg("line").attr("stroke","#999")},d=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},l=function(e){e.fire("rescaled")},h={x:0,y:0},v={x:0,y:0},p={x:0,y:0},m=function(){if(e){var t="matrix("+o+", 0, 0,"+o+","+n+","+r+")";e.attr("transform",t)}},g={getNodeUI:function(e){return a[e]},getLinkUI:function(e){return u[e]},node:function(e){return"function"==typeof e?(s=e,this):void 0},link:function(e){return"function"==typeof e?(c=e,this):void 0},placeNode:function(e){return f=e,this},placeLink:function(e){return d=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,m()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(i,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(i).translate(-u.x,-u.y),f=e.getCTM().multiply(s);o=f.a,n=f.e,r=f.f;var c="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",c),l(this),o},resetScale:function(){o=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),l(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),m(),"function"==typeof i&&i(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(t,n){var r=c(t);if(r)return r.position=n,r.link=t,u[t.id]=r,e.childElementCount>0?e.insertBefore(r,e.firstChild):e.appendChild(r),r},releaseLink:function(t){var n=u[t.id];n&&(e.removeChild(n),delete u[t.id])},addNode:function(t,n){var r=s(t);if(r)return r.position=n,r.node=t,a[t.id]=r,e.appendChild(r),r},releaseNode:function(t){var n=a[t.id];n&&(e.removeChild(n),delete a[t.id])},renderNodes:function(){for(var e in a)if(a.hasOwnProperty(e)){var t=a[e];h.x=t.position.x,h.y=t.position.y,f(t,h,t.node)}},renderLinks:function(){for(var e in u)if(u.hasOwnProperty(e)){var t=u[e];v.x=t.position.from.x,v.y=t.position.from.y,p.x=t.position.to.x,p.y=t.position.to.y,d(t,v,p,t.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):i=e),t},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(g).extend(),g},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,d=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(d.x)+" "+Math.round(d.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),l=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),v=new Float32Array(h),p=new Uint32Array(h),m=0,g=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(p),v=t,p=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(l,d),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;v[n*f]=t.x,v[n*f+1]=t.y,v[n*f+2]=e.size,p[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(p,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,d=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),v=0,p=new ArrayBuffer(16*d),m=new Float32Array(p),g=new Uint32Array(p),y=function(){if((v+1)*d>p.byteLength){var e=new ArrayBuffer(2*p.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,p=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,l),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),v+=1,o=e.id},removeLink:function(e){v>0&&(v-=1),v>e.id&&v>0&&r.copyArrayPart(g,e.id*c,v*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,p,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*v),o=v-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},d=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},l=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},v=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},p=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=l(e),o={offset:e};r.textureNumber>=s.length&&d();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=l(t.offset),r=l(o);p(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],v(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){v(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,d=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),l=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,v=0,p=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(l,d),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;p[n]=t.x-e.size,p[n+1]=t.y-e.size,p[n+2]=4*e._offset,p[n+3]=t.x+e.size,p[n+4]=t.y-e.size,p[n+5]=4*e._offset+1,p[n+6]=t.x-e.size,p[n+7]=t.y+e.size,p[n+8]=4*e._offset+2,p[n+9]=t.x-e.size,p[n+10]=t.y+e.size,p[n+11]=4*e._offset+2,p[n+12]=t.x+e.size,p[n+13]=t.y-e.size,p[n+14]=4*e._offset+1,p[n+15]=t.x+e.size,p[n+16]=t.y+e.size,p[n+17]=4*e._offset+3},createNode:function(t){p=i.extendArray(p,v,c),v+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){v>0&&(v-=1),v>t.id&&v>0&&(t.src&&e.remove(t.src),i.copyArrayPart(p,t.id*c,v*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,p,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*v)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f,c=0,d=0,l=[],h=[],v={},p={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(a),g.updateTransform(a)},V=function(){a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},P=function(e){e.fire("rescaled")},N={getLinkUI:function(e){return p[e]},getNodeUI:function(e){return v[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return u=e,this},placeLink:function(e){return s=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){d>0&&m.render(),c>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(){b()},addLink:function(e,t){var n=d++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,p[e.id]=r,r},addNode:function(e,t){var n=c++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),l[n]=r,v[e.id]=r,r},translateRel:function(e,t){a[12]+=2*a[0]*e/i/a[0],a[13]-=2*a[5]*t/o/a[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=a[12],r-=a[13],a[12]+=n*(1-e),a[13]+=r*(1-e),a[0]*=e,a[5]*=e,w(),P(this),a[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var s="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(s),s}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof f&&f(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){d>0&&(d-=1);var t=p[e.id];delete p[e.id],m.removeLink(t);var n=t.id;if(d>n){if(0===d||d===n)return;var r=h[d];h[n]=r,r.id=n}},releaseNode:function(e){c>0&&(c-=1);var t=v[e.id];delete v[e.id],g.removeNode(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=l[c];l[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;c>t;++t){var n=l[t];e.x=n.position.x,e.y=-n.position.y,u&&u(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;d>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,s&&s(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):f=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-a[12])/a[0],e.y=(e.y-a[13])/a[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;c>n;++n)if(t(l[n],e.x,e.y))return l[n].node;return null}};return Viva.Graph.Utils.events(N).extend(),N},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},i=function(t){return e.getNodeAtClientPos(t,r)},o=null,a=[],u=[],s=[],f=[],c=[],d=[],l=[],h=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},p=function(e){return v(e),!1},m=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(e){var r={x:0,y:0},g=null,y=+new Date,x=function(e){m(c,[g,e]),r.x=e.clientX,r.y=e.clientY},w=function(){h.stop("mousemove",x),h.stop("mouseup",w)},V=function(){n=e.getBoundingClientRect()};window.addEventListener("resize",V),V(),e.addEventListener("mousemove",function(e){if(!o){var t,s=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,t=i(r),t&&g!==t?(g=t,s=s||m(a,[g])):null===t&&g!==t&&(s=s||m(u,[g]),g=null),s&&v(e)}}),e.addEventListener("mousedown",function(e){var o,a=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]?(a=m(s,o),h.on("mousemove",x),h.on("mouseup",w),t=window.document.onselectstart,window.document.onselectstart=p,g=o[0]):g=null,a&&v(e)}),e.addEventListener("mouseup",function(e){var o,a=+new Date;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]&&(window.document.onselectstart=t,400>a-y&&o[0]===g?m(l,o):m(d,o),y=a,m(f,o)&&v(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&l.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file diff --git a/src/View/renderer.js b/src/View/renderer.js index d380098..b2dc379 100644 --- a/src/View/renderer.js +++ b/src/View/renderer.js @@ -286,6 +286,22 @@ Viva.Graph.View.renderer = function (graph, settings) { } }, + scale = function (out, scrollPoint) { + if (!scrollPoint) { + var containerSize = Viva.Graph.Utils.getDimension(container); + scrollPoint = { + x: containerSize.width/2, + y: containerSize.height/2 + }; + } + scrollPoint = scrollPoint || {}; + var scaleFactor = Math.pow(1 + 0.4, out ? -0.2 : 0.2); + transform.scale = graphics.scale(scaleFactor, scrollPoint); + + renderGraph(); + publicEvents.fire('scale', transform.scale); + }, + listenToEvents = function () { windowEvents.on('resize', onWindowResized); @@ -300,11 +316,7 @@ Viva.Graph.View.renderer = function (graph, settings) { }); containerDrag.onScroll(function (e, scaleOffset, scrollPoint) { - var scaleFactor = Math.pow(1 + 0.4, scaleOffset < 0 ? -0.2 : 0.2); - transform.scale = graphics.scale(scaleFactor, scrollPoint); - - renderGraph(); - publicEvents.fire('scale', transform.scale); + scale(scaleOffset < 0, scrollPoint); }); graph.forEachNode(listenNodeEvents); @@ -382,6 +394,14 @@ Viva.Graph.View.renderer = function (graph, settings) { return this; }, + zoomOut: function () { + scale(true); + }, + + zoomIn: function () { + scale(false); + }, + /** * Removes this renderer and deallocates all resources/timers */ From 2b3c1f68771a514174a48cc6a46c78844d909e06 Mon Sep 17 00:00:00 2001 From: Andrei Kashcha Date: Thu, 19 Dec 2013 13:28:29 -0800 Subject: [PATCH 057/276] Showing recommended way of pinning. --- demos/other/pinNode.html | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/demos/other/pinNode.html b/demos/other/pinNode.html index 3bc3a2d..289c416 100644 --- a/demos/other/pinNode.html +++ b/demos/other/pinNode.html @@ -23,12 +23,7 @@ // to not update node's position. Effectively the node looks // like it is pinned to the canvas. - // One way to achieve pinning is to have "isPinned" attribute on - // node object: - // var node = graph.addNode('yourNodeId', {some: data}); - // node.isPinned = true; // now the node will not move. - - // You can also pin/unpin node any time you want: + // You can pin/unpin node any time you want: graphics.node(function (node) { var ui = Viva.Graph.svg("rect") .attr("width", 10) From ed697a117638597c732ed6b7fbb196286d5ed363 Mon Sep 17 00:00:00 2001 From: anvaka Date: Thu, 26 Dec 2013 23:52:56 -0800 Subject: [PATCH 058/276] Removed redundant statement --- src/View/renderer.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/View/renderer.js b/src/View/renderer.js index b2dc379..38c8142 100644 --- a/src/View/renderer.js +++ b/src/View/renderer.js @@ -294,7 +294,6 @@ Viva.Graph.View.renderer = function (graph, settings) { y: containerSize.height/2 }; } - scrollPoint = scrollPoint || {}; var scaleFactor = Math.pow(1 + 0.4, out ? -0.2 : 0.2); transform.scale = graphics.scale(scaleFactor, scrollPoint); From 2bb03cacb192d8580353cef19a5138653890b8e0 Mon Sep 17 00:00:00 2001 From: anvaka Date: Fri, 27 Dec 2013 00:16:19 -0800 Subject: [PATCH 059/276] Added pan support This currently works for svg only --- demos/other/zoomPanAPI.html | 31 +++++++++++++++++++++++++++++-- dist/vivagraph.js | 18 ++++++++++++++++-- dist/vivagraph.min.js | 4 ++-- src/View/renderer.js | 17 ++++++++++++++++- 4 files changed, 63 insertions(+), 7 deletions(-) diff --git a/demos/other/zoomPanAPI.html b/demos/other/zoomPanAPI.html index cf6de53..2fb4c3c 100644 --- a/demos/other/zoomPanAPI.html +++ b/demos/other/zoomPanAPI.html @@ -18,11 +18,12 @@ }); var renderer = Viva.Graph.View.renderer(graph, { - layout : layout, - }); + layout : layout + }); renderer.run(); + var graphics = renderer.getGraphics(); $('.zoom').click(function (e) { e.preventDefault(); if ($(this).hasClass('in')) { @@ -31,9 +32,32 @@ renderer.zoomOut(); } }); + + + $('#centerForm').submit(function(e) { + e.preventDefault(); + var nodeId = $('#nodeid').val(); + if (graph.getNode(nodeId)) { + var pos = layout.getNodePosition(nodeId); + renderer.moveTo(pos.x, pos.y); + + highlightNode(nodeId); + } + }); + $('.reset').click(function () { renderer.reset() }); + + var prevSelected; + function highlightNode(nodeId) { + var ui = graphics.getNodeUI(nodeId); + if (prevSelected) { + prevSelected.attr('fill', '#00a2e8') + } + prevSelected = ui; + ui.attr('fill', 'orange'); + } } @@ -51,6 +75,9 @@
Zoom In | Zoom Out
Reset +
+ Center on node (0-99): +
diff --git a/dist/vivagraph.js b/dist/vivagraph.js index ce59d6f..75f1f5d 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -2889,7 +2889,7 @@ Viva.Graph.View.renderer = function (graph, settings) { viewPortOffset.x = viewPortOffset.y = 0; transform.offsetX = containerSize.width / 2 - (graphRect.x2 + graphRect.x1) / 2; transform.offsetY = containerSize.height / 2 - (graphRect.y2 + graphRect.y1) / 2; - graphics.graphCenterChanged(transform.offsetX + viewPortOffset.x, transform.offsetY + viewPortOffset.y); + graphics.graphCenterChanged(transform.offsetX, transform.offsetY); updateCenterRequired = false; }, @@ -3035,7 +3035,6 @@ Viva.Graph.View.renderer = function (graph, settings) { y: containerSize.height/2 }; } - scrollPoint = scrollPoint || {}; var scaleFactor = Math.pow(1 + 0.4, out ? -0.2 : 0.2); transform.scale = graphics.scale(scaleFactor, scrollPoint); @@ -3143,6 +3142,21 @@ Viva.Graph.View.renderer = function (graph, settings) { scale(false); }, + /** + * Centers renderer at x,y graph's coordinates + */ + moveTo: function (x, y) { + graphics.graphCenterChanged(transform.offsetX - x * transform.scale, transform.offsetY - y * transform.scale); + renderGraph(); + }, + + /** + * Gets current graphics object + */ + getGraphics: function () { + return graphics; + }, + /** * Removes this renderer and deallocates all resources/timers */ diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 1cfa01d..09ab730 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.2",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},P=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},N=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",P,!1):e.addEventListener("DOMMouseScroll",P,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",P,!1):e.removeEventListener("DOMMouseScroll",P,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),N(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,d=Math.sqrt(f*f+c*c);d>r&&(u.velocity.x=r*f/d,u.velocity.y=r*c/d),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};r="number"==typeof r?r:1;var o=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,r);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02,springTransform:function(){},timeStep:20});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),f={},c=function(e){if(e.position)return e.position;var n=(u.x1+u.x2)/2,r=(u.y1+u.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],a=o.fromId!==e.id?f[o.fromId]:f[o.toId];a&&a.location&&(n=a.location.x,r=a.location.y)}return{x:n+s.next(i)-i/2,y:r+s.next(i)-i/2}},d=function(e){return f[e]},l=function(e){f[e]=null,delete f[e]},h={},v=function(t){var n=d(t);n.mass=1+e.getLinks(t).length/3},p=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},m=function(e){return e.isPinned},g=function(t){var n=d(t);if(!n){var i=e.getNode(t);if(!i)return;n=new Viva.Graph.Physics.Body,f[t]=n;var o=c(i);n.loc(o),v(t),p(i)&&(n.isPinned=!0),r.addBody(n)}},y=function(e){g(e.id)},x=function(t){var n=d(t.id);n&&(l(t.id),r.removeBody(n),0===e.getNodesCount()&&(u.x1=u.y1=0,u.x2=u.y2=0))},w=function(e){v(e.fromId),v(e.toId);var n=d(e.fromId),i=d(e.toId),o=r.addSpring(n,i,-1,e.weight);t.springTransform(e,o),h[e.id]=o},V=function(t){var n=h[t.id];if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&v(i.id),o&&v(o.id),delete h[t.id],r.removeSpring(n)}},b=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&g(n.node.id),n.link&&w(n.link)):"remove"===n.changeType&&(n.node&&x(n.node),n.link&&V(n.link))}},P=function(){e.forEachNode(y),e.forEachLink(w),e.addEventListener("changed",b)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in f)if(f.hasOwnProperty(o)){var a=f[o];m(a)?(a.location.x=a.prevLocation.x,a.location.y=a.prevLocation.y):(a.prevLocation.x=a.location.x,a.prevLocation.y=a.location.y),t>a.location.x&&(t=a.location.x),a.location.x>r&&(r=a.location.x),n>a.location.y&&(n=a.location.y),a.location.y>i&&(i=a.location.y)}u.x1=t,u.x2=r,u.y1=n,u.y2=i}};return r.setSpringForce(o),r.setNbodyForce(i),r.setDragForce(a),P(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(t.timeStep);return N(),n>e},isNodePinned:function(e){var t=d(e.id);return t?m(t):void 0},pinNode:function(e,t){var n=d(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=d(e);return t||(g(e),t=d(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=d(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",b)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a={},u=function(e){e&&(a[e.id]||(a[e.id]=i(e)),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&u(n.node)}};return{run:function(){this.step()},step:function(){return s(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,d=!0,l=0,h=0,v=!1,p=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return v=u.step()&&!p,V(),!v},P=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(l=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},N=function(){v=!1,i.restart()},E=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX+m.x,g.offsetY+m.y),d=!1},L=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),p=!0,N()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),p=!0,V()},onStop:function(){u.pinNode(e,t),p=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),d&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(d=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},D=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);N()},R=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",D),o=null)},z=function(e,t){if(!t){var n=Viva.Graph.Utils.getDimension(f);t={x:n.width/2,y:n.height/2}}t=t||{};var r=Math.pow(1.4,e?-.2:.2);g.scale=s.scale(r,t),V(),w.fire("scale",g.scale)},B=function(){x.on("resize",R),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){z(0>t,n)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",D)},Y=function(){c=!1,O(),F(),x.stop("resize",R),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),E(),G(),C(),B(),c=!0),P(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},zoomOut:function(){z(!0)},zoomIn:function(){z(!1)},dispose:function(){Y()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e) -}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},d=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},l=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?d(e):(d=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,l()},translateRel:function(e,r){t+=e,n+=r,l()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,l()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),d=f.attr("id"),l=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&d===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&l===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i,o=1,a={},u={},s=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},f=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},c=function(){return Viva.Graph.svg("line").attr("stroke","#999")},d=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},l=function(e){e.fire("rescaled")},h={x:0,y:0},v={x:0,y:0},p={x:0,y:0},m=function(){if(e){var t="matrix("+o+", 0, 0,"+o+","+n+","+r+")";e.attr("transform",t)}},g={getNodeUI:function(e){return a[e]},getLinkUI:function(e){return u[e]},node:function(e){return"function"==typeof e?(s=e,this):void 0},link:function(e){return"function"==typeof e?(c=e,this):void 0},placeNode:function(e){return f=e,this},placeLink:function(e){return d=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,m()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(i,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(i).translate(-u.x,-u.y),f=e.getCTM().multiply(s);o=f.a,n=f.e,r=f.f;var c="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",c),l(this),o},resetScale:function(){o=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),l(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),m(),"function"==typeof i&&i(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(t,n){var r=c(t);if(r)return r.position=n,r.link=t,u[t.id]=r,e.childElementCount>0?e.insertBefore(r,e.firstChild):e.appendChild(r),r},releaseLink:function(t){var n=u[t.id];n&&(e.removeChild(n),delete u[t.id])},addNode:function(t,n){var r=s(t);if(r)return r.position=n,r.node=t,a[t.id]=r,e.appendChild(r),r},releaseNode:function(t){var n=a[t.id];n&&(e.removeChild(n),delete a[t.id])},renderNodes:function(){for(var e in a)if(a.hasOwnProperty(e)){var t=a[e];h.x=t.position.x,h.y=t.position.y,f(t,h,t.node)}},renderLinks:function(){for(var e in u)if(u.hasOwnProperty(e)){var t=u[e];v.x=t.position.from.x,v.y=t.position.from.y,p.x=t.position.to.x,p.y=t.position.to.y,d(t,v,p,t.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):i=e),t},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(g).extend(),g},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,d=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(d.x)+" "+Math.round(d.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),l=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),v=new Float32Array(h),p=new Uint32Array(h),m=0,g=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(p),v=t,p=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(l,d),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;v[n*f]=t.x,v[n*f+1]=t.y,v[n*f+2]=e.size,p[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(p,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,d=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),v=0,p=new ArrayBuffer(16*d),m=new Float32Array(p),g=new Uint32Array(p),y=function(){if((v+1)*d>p.byteLength){var e=new ArrayBuffer(2*p.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,p=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,l),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),v+=1,o=e.id},removeLink:function(e){v>0&&(v-=1),v>e.id&&v>0&&r.copyArrayPart(g,e.id*c,v*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,p,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*v),o=v-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},d=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},l=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},v=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},p=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=l(e),o={offset:e};r.textureNumber>=s.length&&d();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=l(t.offset),r=l(o);p(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],v(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){v(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,d=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),l=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,v=0,p=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(l,d),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;p[n]=t.x-e.size,p[n+1]=t.y-e.size,p[n+2]=4*e._offset,p[n+3]=t.x+e.size,p[n+4]=t.y-e.size,p[n+5]=4*e._offset+1,p[n+6]=t.x-e.size,p[n+7]=t.y+e.size,p[n+8]=4*e._offset+2,p[n+9]=t.x-e.size,p[n+10]=t.y+e.size,p[n+11]=4*e._offset+2,p[n+12]=t.x+e.size,p[n+13]=t.y-e.size,p[n+14]=4*e._offset+1,p[n+15]=t.x+e.size,p[n+16]=t.y+e.size,p[n+17]=4*e._offset+3},createNode:function(t){p=i.extendArray(p,v,c),v+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){v>0&&(v-=1),v>t.id&&v>0&&(t.src&&e.remove(t.src),i.copyArrayPart(p,t.id*c,v*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,p,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*v)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f,c=0,d=0,l=[],h=[],v={},p={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(a),g.updateTransform(a)},V=function(){a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},P=function(e){e.fire("rescaled")},N={getLinkUI:function(e){return p[e]},getNodeUI:function(e){return v[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return u=e,this},placeLink:function(e){return s=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){d>0&&m.render(),c>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(){b()},addLink:function(e,t){var n=d++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,p[e.id]=r,r},addNode:function(e,t){var n=c++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),l[n]=r,v[e.id]=r,r},translateRel:function(e,t){a[12]+=2*a[0]*e/i/a[0],a[13]-=2*a[5]*t/o/a[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=a[12],r-=a[13],a[12]+=n*(1-e),a[13]+=r*(1-e),a[0]*=e,a[5]*=e,w(),P(this),a[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var s="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(s),s}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof f&&f(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){d>0&&(d-=1);var t=p[e.id];delete p[e.id],m.removeLink(t);var n=t.id;if(d>n){if(0===d||d===n)return;var r=h[d];h[n]=r,r.id=n}},releaseNode:function(e){c>0&&(c-=1);var t=v[e.id];delete v[e.id],g.removeNode(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=l[c];l[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;c>t;++t){var n=l[t];e.x=n.position.x,e.y=-n.position.y,u&&u(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;d>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,s&&s(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):f=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-a[12])/a[0],e.y=(e.y-a[13])/a[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;c>n;++n)if(t(l[n],e.x,e.y))return l[n].node;return null}};return Viva.Graph.Utils.events(N).extend(),N},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},i=function(t){return e.getNodeAtClientPos(t,r)},o=null,a=[],u=[],s=[],f=[],c=[],d=[],l=[],h=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},p=function(e){return v(e),!1},m=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(e){var r={x:0,y:0},g=null,y=+new Date,x=function(e){m(c,[g,e]),r.x=e.clientX,r.y=e.clientY},w=function(){h.stop("mousemove",x),h.stop("mouseup",w)},V=function(){n=e.getBoundingClientRect()};window.addEventListener("resize",V),V(),e.addEventListener("mousemove",function(e){if(!o){var t,s=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,t=i(r),t&&g!==t?(g=t,s=s||m(a,[g])):null===t&&g!==t&&(s=s||m(u,[g]),g=null),s&&v(e)}}),e.addEventListener("mousedown",function(e){var o,a=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]?(a=m(s,o),h.on("mousemove",x),h.on("mouseup",w),t=window.document.onselectstart,window.document.onselectstart=p,g=o[0]):g=null,a&&v(e)}),e.addEventListener("mouseup",function(e){var o,a=+new Date;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]&&(window.document.onselectstart=t,400>a-y&&o[0]===g?m(l,o):m(d,o),y=a,m(f,o)&&v(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&l.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file +var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.2",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},P=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},N=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",P,!1):e.addEventListener("DOMMouseScroll",P,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",P,!1):e.removeEventListener("DOMMouseScroll",P,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),N(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,d=Math.sqrt(f*f+c*c);d>r&&(u.velocity.x=r*f/d,u.velocity.y=r*c/d),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};r="number"==typeof r?r:1;var o=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,r);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02,springTransform:function(){},timeStep:20});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),f={},c=function(e){if(e.position)return e.position;var n=(u.x1+u.x2)/2,r=(u.y1+u.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],a=o.fromId!==e.id?f[o.fromId]:f[o.toId];a&&a.location&&(n=a.location.x,r=a.location.y)}return{x:n+s.next(i)-i/2,y:r+s.next(i)-i/2}},d=function(e){return f[e]},l=function(e){f[e]=null,delete f[e]},h={},v=function(t){var n=d(t);n.mass=1+e.getLinks(t).length/3},p=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},m=function(e){return e.isPinned},g=function(t){var n=d(t);if(!n){var i=e.getNode(t);if(!i)return;n=new Viva.Graph.Physics.Body,f[t]=n;var o=c(i);n.loc(o),v(t),p(i)&&(n.isPinned=!0),r.addBody(n)}},y=function(e){g(e.id)},x=function(t){var n=d(t.id);n&&(l(t.id),r.removeBody(n),0===e.getNodesCount()&&(u.x1=u.y1=0,u.x2=u.y2=0))},w=function(e){v(e.fromId),v(e.toId);var n=d(e.fromId),i=d(e.toId),o=r.addSpring(n,i,-1,e.weight);t.springTransform(e,o),h[e.id]=o},V=function(t){var n=h[t.id];if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&v(i.id),o&&v(o.id),delete h[t.id],r.removeSpring(n)}},b=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&g(n.node.id),n.link&&w(n.link)):"remove"===n.changeType&&(n.node&&x(n.node),n.link&&V(n.link))}},P=function(){e.forEachNode(y),e.forEachLink(w),e.addEventListener("changed",b)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in f)if(f.hasOwnProperty(o)){var a=f[o];m(a)?(a.location.x=a.prevLocation.x,a.location.y=a.prevLocation.y):(a.prevLocation.x=a.location.x,a.prevLocation.y=a.location.y),t>a.location.x&&(t=a.location.x),a.location.x>r&&(r=a.location.x),n>a.location.y&&(n=a.location.y),a.location.y>i&&(i=a.location.y)}u.x1=t,u.x2=r,u.y1=n,u.y2=i}};return r.setSpringForce(o),r.setNbodyForce(i),r.setDragForce(a),P(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(t.timeStep);return N(),n>e},isNodePinned:function(e){var t=d(e.id);return t?m(t):void 0},pinNode:function(e,t){var n=d(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=d(e);return t||(g(e),t=d(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=d(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",b)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a={},u=function(e){e&&(a[e.id]||(a[e.id]=i(e)),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&u(n.node)}};return{run:function(){this.step()},step:function(){return s(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,d=!0,l=0,h=0,v=!1,p=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return v=u.step()&&!p,V(),!v},P=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(l=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},N=function(){v=!1,i.restart()},E=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX,g.offsetY),d=!1},L=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),p=!0,N()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),p=!0,V()},onStop:function(){u.pinNode(e,t),p=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),d&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(d=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},D=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);N()},R=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",D),o=null)},z=function(e,t){if(!t){var n=Viva.Graph.Utils.getDimension(f);t={x:n.width/2,y:n.height/2}}var r=Math.pow(1.4,e?-.2:.2);g.scale=s.scale(r,t),V(),w.fire("scale",g.scale)},B=function(){x.on("resize",R),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){z(0>t,n)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",D)},Y=function(){c=!1,O(),F(),x.stop("resize",R),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),E(),G(),C(),B(),c=!0),P(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},zoomOut:function(){z(!0)},zoomIn:function(){z(!1)},moveTo:function(e,t){s.graphCenterChanged(g.offsetX-e*g.scale,g.offsetY-t*g.scale),V()},getGraphics:function(){return s},dispose:function(){Y()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph(); +for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},d=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},l=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?d(e):(d=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,l()},translateRel:function(e,r){t+=e,n+=r,l()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,l()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),d=f.attr("id"),l=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&d===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&l===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i,o=1,a={},u={},s=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},f=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},c=function(){return Viva.Graph.svg("line").attr("stroke","#999")},d=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},l=function(e){e.fire("rescaled")},h={x:0,y:0},v={x:0,y:0},p={x:0,y:0},m=function(){if(e){var t="matrix("+o+", 0, 0,"+o+","+n+","+r+")";e.attr("transform",t)}},g={getNodeUI:function(e){return a[e]},getLinkUI:function(e){return u[e]},node:function(e){return"function"==typeof e?(s=e,this):void 0},link:function(e){return"function"==typeof e?(c=e,this):void 0},placeNode:function(e){return f=e,this},placeLink:function(e){return d=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,m()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(i,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(i).translate(-u.x,-u.y),f=e.getCTM().multiply(s);o=f.a,n=f.e,r=f.f;var c="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",c),l(this),o},resetScale:function(){o=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),l(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),m(),"function"==typeof i&&i(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(t,n){var r=c(t);if(r)return r.position=n,r.link=t,u[t.id]=r,e.childElementCount>0?e.insertBefore(r,e.firstChild):e.appendChild(r),r},releaseLink:function(t){var n=u[t.id];n&&(e.removeChild(n),delete u[t.id])},addNode:function(t,n){var r=s(t);if(r)return r.position=n,r.node=t,a[t.id]=r,e.appendChild(r),r},releaseNode:function(t){var n=a[t.id];n&&(e.removeChild(n),delete a[t.id])},renderNodes:function(){for(var e in a)if(a.hasOwnProperty(e)){var t=a[e];h.x=t.position.x,h.y=t.position.y,f(t,h,t.node)}},renderLinks:function(){for(var e in u)if(u.hasOwnProperty(e)){var t=u[e];v.x=t.position.from.x,v.y=t.position.from.y,p.x=t.position.to.x,p.y=t.position.to.y,d(t,v,p,t.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):i=e),t},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(g).extend(),g},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,d=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(d.x)+" "+Math.round(d.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),l=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),v=new Float32Array(h),p=new Uint32Array(h),m=0,g=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(p),v=t,p=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(l,d),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;v[n*f]=t.x,v[n*f+1]=t.y,v[n*f+2]=e.size,p[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(p,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,d=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),v=0,p=new ArrayBuffer(16*d),m=new Float32Array(p),g=new Uint32Array(p),y=function(){if((v+1)*d>p.byteLength){var e=new ArrayBuffer(2*p.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,p=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,l),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),v+=1,o=e.id},removeLink:function(e){v>0&&(v-=1),v>e.id&&v>0&&r.copyArrayPart(g,e.id*c,v*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,p,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*v),o=v-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},d=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},l=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},v=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},p=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=l(e),o={offset:e};r.textureNumber>=s.length&&d();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=l(t.offset),r=l(o);p(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],v(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){v(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,d=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),l=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,v=0,p=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(l,d),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;p[n]=t.x-e.size,p[n+1]=t.y-e.size,p[n+2]=4*e._offset,p[n+3]=t.x+e.size,p[n+4]=t.y-e.size,p[n+5]=4*e._offset+1,p[n+6]=t.x-e.size,p[n+7]=t.y+e.size,p[n+8]=4*e._offset+2,p[n+9]=t.x-e.size,p[n+10]=t.y+e.size,p[n+11]=4*e._offset+2,p[n+12]=t.x+e.size,p[n+13]=t.y-e.size,p[n+14]=4*e._offset+1,p[n+15]=t.x+e.size,p[n+16]=t.y+e.size,p[n+17]=4*e._offset+3},createNode:function(t){p=i.extendArray(p,v,c),v+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){v>0&&(v-=1),v>t.id&&v>0&&(t.src&&e.remove(t.src),i.copyArrayPart(p,t.id*c,v*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,p,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*v)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f,c=0,d=0,l=[],h=[],v={},p={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(a),g.updateTransform(a)},V=function(){a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},P=function(e){e.fire("rescaled")},N={getLinkUI:function(e){return p[e]},getNodeUI:function(e){return v[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return u=e,this},placeLink:function(e){return s=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){d>0&&m.render(),c>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(){b()},addLink:function(e,t){var n=d++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,p[e.id]=r,r},addNode:function(e,t){var n=c++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),l[n]=r,v[e.id]=r,r},translateRel:function(e,t){a[12]+=2*a[0]*e/i/a[0],a[13]-=2*a[5]*t/o/a[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=a[12],r-=a[13],a[12]+=n*(1-e),a[13]+=r*(1-e),a[0]*=e,a[5]*=e,w(),P(this),a[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var s="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(s),s}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof f&&f(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){d>0&&(d-=1);var t=p[e.id];delete p[e.id],m.removeLink(t);var n=t.id;if(d>n){if(0===d||d===n)return;var r=h[d];h[n]=r,r.id=n}},releaseNode:function(e){c>0&&(c-=1);var t=v[e.id];delete v[e.id],g.removeNode(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=l[c];l[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;c>t;++t){var n=l[t];e.x=n.position.x,e.y=-n.position.y,u&&u(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;d>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,s&&s(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):f=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-a[12])/a[0],e.y=(e.y-a[13])/a[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;c>n;++n)if(t(l[n],e.x,e.y))return l[n].node;return null}};return Viva.Graph.Utils.events(N).extend(),N},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},i=function(t){return e.getNodeAtClientPos(t,r)},o=null,a=[],u=[],s=[],f=[],c=[],d=[],l=[],h=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},p=function(e){return v(e),!1},m=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(e){var r={x:0,y:0},g=null,y=+new Date,x=function(e){m(c,[g,e]),r.x=e.clientX,r.y=e.clientY},w=function(){h.stop("mousemove",x),h.stop("mouseup",w)},V=function(){n=e.getBoundingClientRect()};window.addEventListener("resize",V),V(),e.addEventListener("mousemove",function(e){if(!o){var t,s=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,t=i(r),t&&g!==t?(g=t,s=s||m(a,[g])):null===t&&g!==t&&(s=s||m(u,[g]),g=null),s&&v(e)}}),e.addEventListener("mousedown",function(e){var o,a=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]?(a=m(s,o),h.on("mousemove",x),h.on("mouseup",w),t=window.document.onselectstart,window.document.onselectstart=p,g=o[0]):g=null,a&&v(e)}),e.addEventListener("mouseup",function(e){var o,a=+new Date;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]&&(window.document.onselectstart=t,400>a-y&&o[0]===g?m(l,o):m(d,o),y=a,m(f,o)&&v(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&l.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file diff --git a/src/View/renderer.js b/src/View/renderer.js index 38c8142..d3cc489 100644 --- a/src/View/renderer.js +++ b/src/View/renderer.js @@ -148,7 +148,7 @@ Viva.Graph.View.renderer = function (graph, settings) { viewPortOffset.x = viewPortOffset.y = 0; transform.offsetX = containerSize.width / 2 - (graphRect.x2 + graphRect.x1) / 2; transform.offsetY = containerSize.height / 2 - (graphRect.y2 + graphRect.y1) / 2; - graphics.graphCenterChanged(transform.offsetX + viewPortOffset.x, transform.offsetY + viewPortOffset.y); + graphics.graphCenterChanged(transform.offsetX, transform.offsetY); updateCenterRequired = false; }, @@ -401,6 +401,21 @@ Viva.Graph.View.renderer = function (graph, settings) { scale(false); }, + /** + * Centers renderer at x,y graph's coordinates + */ + moveTo: function (x, y) { + graphics.graphCenterChanged(transform.offsetX - x * transform.scale, transform.offsetY - y * transform.scale); + renderGraph(); + }, + + /** + * Gets current graphics object + */ + getGraphics: function () { + return graphics; + }, + /** * Removes this renderer and deallocates all resources/timers */ From 9416d39cb409597c30b27aac83d1a240c432b4ab Mon Sep 17 00:00:00 2001 From: anvaka Date: Fri, 27 Dec 2013 00:37:21 -0800 Subject: [PATCH 060/276] 0.5.3 --- CHANGELOG | 5 +++++ dist/vivagraph.js | 4 ++-- dist/vivagraph.min.js | 2 +- src/View/webglGraphics.js | 2 +- src/version.js | 2 +- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 8fd8a49..e902a91 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,8 @@ +v0.5.3 + date: Dec 27, 2013 + - Small clean up in renderer + - Added pan/zoom API for SVG + v0.5.2 date: Nov 23, 2013 - Euler integrator now supports custom time step diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 75f1f5d..6f83ec6 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -7,7 +7,7 @@ Viva.Graph = Viva.Graph || {}; if (typeof module !== 'undefined' && module.exports) { module.exports = Viva; } -Viva.Graph.version = '0.5.2'; +Viva.Graph.version = '0.5.3'; /** * Extends target object with given fields/values in the options object. * Unlike jQuery's extend this method does not override target object @@ -5996,7 +5996,7 @@ Viva.Graph.View.webglGraphics = function (options) { links[srcLinkId].id = srcLinkId; } }, -/*jshint unused: false */ + /** * Sets translate operation that should be applied to all nodes and links. */ diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 09ab730..1ac503c 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.2",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},P=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},N=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",P,!1):e.addEventListener("DOMMouseScroll",P,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",P,!1):e.removeEventListener("DOMMouseScroll",P,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),N(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,d=Math.sqrt(f*f+c*c);d>r&&(u.velocity.x=r*f/d,u.velocity.y=r*c/d),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};r="number"==typeof r?r:1;var o=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,r);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02,springTransform:function(){},timeStep:20});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),f={},c=function(e){if(e.position)return e.position;var n=(u.x1+u.x2)/2,r=(u.y1+u.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],a=o.fromId!==e.id?f[o.fromId]:f[o.toId];a&&a.location&&(n=a.location.x,r=a.location.y)}return{x:n+s.next(i)-i/2,y:r+s.next(i)-i/2}},d=function(e){return f[e]},l=function(e){f[e]=null,delete f[e]},h={},v=function(t){var n=d(t);n.mass=1+e.getLinks(t).length/3},p=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},m=function(e){return e.isPinned},g=function(t){var n=d(t);if(!n){var i=e.getNode(t);if(!i)return;n=new Viva.Graph.Physics.Body,f[t]=n;var o=c(i);n.loc(o),v(t),p(i)&&(n.isPinned=!0),r.addBody(n)}},y=function(e){g(e.id)},x=function(t){var n=d(t.id);n&&(l(t.id),r.removeBody(n),0===e.getNodesCount()&&(u.x1=u.y1=0,u.x2=u.y2=0))},w=function(e){v(e.fromId),v(e.toId);var n=d(e.fromId),i=d(e.toId),o=r.addSpring(n,i,-1,e.weight);t.springTransform(e,o),h[e.id]=o},V=function(t){var n=h[t.id];if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&v(i.id),o&&v(o.id),delete h[t.id],r.removeSpring(n)}},b=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&g(n.node.id),n.link&&w(n.link)):"remove"===n.changeType&&(n.node&&x(n.node),n.link&&V(n.link))}},P=function(){e.forEachNode(y),e.forEachLink(w),e.addEventListener("changed",b)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in f)if(f.hasOwnProperty(o)){var a=f[o];m(a)?(a.location.x=a.prevLocation.x,a.location.y=a.prevLocation.y):(a.prevLocation.x=a.location.x,a.prevLocation.y=a.location.y),t>a.location.x&&(t=a.location.x),a.location.x>r&&(r=a.location.x),n>a.location.y&&(n=a.location.y),a.location.y>i&&(i=a.location.y)}u.x1=t,u.x2=r,u.y1=n,u.y2=i}};return r.setSpringForce(o),r.setNbodyForce(i),r.setDragForce(a),P(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(t.timeStep);return N(),n>e},isNodePinned:function(e){var t=d(e.id);return t?m(t):void 0},pinNode:function(e,t){var n=d(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=d(e);return t||(g(e),t=d(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=d(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",b)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a={},u=function(e){e&&(a[e.id]||(a[e.id]=i(e)),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&u(n.node)}};return{run:function(){this.step()},step:function(){return s(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,d=!0,l=0,h=0,v=!1,p=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return v=u.step()&&!p,V(),!v},P=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(l=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},N=function(){v=!1,i.restart()},E=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX,g.offsetY),d=!1},L=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),p=!0,N()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),p=!0,V()},onStop:function(){u.pinNode(e,t),p=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),d&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(d=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},D=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);N()},R=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",D),o=null)},z=function(e,t){if(!t){var n=Viva.Graph.Utils.getDimension(f);t={x:n.width/2,y:n.height/2}}var r=Math.pow(1.4,e?-.2:.2);g.scale=s.scale(r,t),V(),w.fire("scale",g.scale)},B=function(){x.on("resize",R),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){z(0>t,n)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",D)},Y=function(){c=!1,O(),F(),x.stop("resize",R),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),E(),G(),C(),B(),c=!0),P(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},zoomOut:function(){z(!0)},zoomIn:function(){z(!1)},moveTo:function(e,t){s.graphCenterChanged(g.offsetX-e*g.scale,g.offsetY-t*g.scale),V()},getGraphics:function(){return s},dispose:function(){Y()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph(); +var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.3",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},P=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},N=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",P,!1):e.addEventListener("DOMMouseScroll",P,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",P,!1):e.removeEventListener("DOMMouseScroll",P,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),N(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,d=Math.sqrt(f*f+c*c);d>r&&(u.velocity.x=r*f/d,u.velocity.y=r*c/d),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};r="number"==typeof r?r:1;var o=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,r);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02,springTransform:function(){},timeStep:20});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),f={},c=function(e){if(e.position)return e.position;var n=(u.x1+u.x2)/2,r=(u.y1+u.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],a=o.fromId!==e.id?f[o.fromId]:f[o.toId];a&&a.location&&(n=a.location.x,r=a.location.y)}return{x:n+s.next(i)-i/2,y:r+s.next(i)-i/2}},d=function(e){return f[e]},l=function(e){f[e]=null,delete f[e]},h={},v=function(t){var n=d(t);n.mass=1+e.getLinks(t).length/3},p=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},m=function(e){return e.isPinned},g=function(t){var n=d(t);if(!n){var i=e.getNode(t);if(!i)return;n=new Viva.Graph.Physics.Body,f[t]=n;var o=c(i);n.loc(o),v(t),p(i)&&(n.isPinned=!0),r.addBody(n)}},y=function(e){g(e.id)},x=function(t){var n=d(t.id);n&&(l(t.id),r.removeBody(n),0===e.getNodesCount()&&(u.x1=u.y1=0,u.x2=u.y2=0))},w=function(e){v(e.fromId),v(e.toId);var n=d(e.fromId),i=d(e.toId),o=r.addSpring(n,i,-1,e.weight);t.springTransform(e,o),h[e.id]=o},V=function(t){var n=h[t.id];if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&v(i.id),o&&v(o.id),delete h[t.id],r.removeSpring(n)}},b=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&g(n.node.id),n.link&&w(n.link)):"remove"===n.changeType&&(n.node&&x(n.node),n.link&&V(n.link))}},P=function(){e.forEachNode(y),e.forEachLink(w),e.addEventListener("changed",b)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in f)if(f.hasOwnProperty(o)){var a=f[o];m(a)?(a.location.x=a.prevLocation.x,a.location.y=a.prevLocation.y):(a.prevLocation.x=a.location.x,a.prevLocation.y=a.location.y),t>a.location.x&&(t=a.location.x),a.location.x>r&&(r=a.location.x),n>a.location.y&&(n=a.location.y),a.location.y>i&&(i=a.location.y)}u.x1=t,u.x2=r,u.y1=n,u.y2=i}};return r.setSpringForce(o),r.setNbodyForce(i),r.setDragForce(a),P(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(t.timeStep);return N(),n>e},isNodePinned:function(e){var t=d(e.id);return t?m(t):void 0},pinNode:function(e,t){var n=d(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=d(e);return t||(g(e),t=d(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=d(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",b)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a={},u=function(e){e&&(a[e.id]||(a[e.id]=i(e)),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&u(n.node)}};return{run:function(){this.step()},step:function(){return s(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,d=!0,l=0,h=0,v=!1,p=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return v=u.step()&&!p,V(),!v},P=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(l=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},N=function(){v=!1,i.restart()},E=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX,g.offsetY),d=!1},L=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),p=!0,N()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),p=!0,V()},onStop:function(){u.pinNode(e,t),p=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),d&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(d=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},D=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);N()},R=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",D),o=null)},z=function(e,t){if(!t){var n=Viva.Graph.Utils.getDimension(f);t={x:n.width/2,y:n.height/2}}var r=Math.pow(1.4,e?-.2:.2);g.scale=s.scale(r,t),V(),w.fire("scale",g.scale)},B=function(){x.on("resize",R),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){z(0>t,n)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",D)},Y=function(){c=!1,O(),F(),x.stop("resize",R),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),E(),G(),C(),B(),c=!0),P(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},zoomOut:function(){z(!0)},zoomIn:function(){z(!1)},moveTo:function(e,t){s.graphCenterChanged(g.offsetX-e*g.scale,g.offsetY-t*g.scale),V()},getGraphics:function(){return s},dispose:function(){Y()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph(); for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},d=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},l=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?d(e):(d=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,l()},translateRel:function(e,r){t+=e,n+=r,l()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,l()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),d=f.attr("id"),l=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&d===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&l===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i,o=1,a={},u={},s=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},f=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},c=function(){return Viva.Graph.svg("line").attr("stroke","#999")},d=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},l=function(e){e.fire("rescaled")},h={x:0,y:0},v={x:0,y:0},p={x:0,y:0},m=function(){if(e){var t="matrix("+o+", 0, 0,"+o+","+n+","+r+")";e.attr("transform",t)}},g={getNodeUI:function(e){return a[e]},getLinkUI:function(e){return u[e]},node:function(e){return"function"==typeof e?(s=e,this):void 0},link:function(e){return"function"==typeof e?(c=e,this):void 0},placeNode:function(e){return f=e,this},placeLink:function(e){return d=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,m()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(i,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(i).translate(-u.x,-u.y),f=e.getCTM().multiply(s);o=f.a,n=f.e,r=f.f;var c="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",c),l(this),o},resetScale:function(){o=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),l(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),m(),"function"==typeof i&&i(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(t,n){var r=c(t);if(r)return r.position=n,r.link=t,u[t.id]=r,e.childElementCount>0?e.insertBefore(r,e.firstChild):e.appendChild(r),r},releaseLink:function(t){var n=u[t.id];n&&(e.removeChild(n),delete u[t.id])},addNode:function(t,n){var r=s(t);if(r)return r.position=n,r.node=t,a[t.id]=r,e.appendChild(r),r},releaseNode:function(t){var n=a[t.id];n&&(e.removeChild(n),delete a[t.id])},renderNodes:function(){for(var e in a)if(a.hasOwnProperty(e)){var t=a[e];h.x=t.position.x,h.y=t.position.y,f(t,h,t.node)}},renderLinks:function(){for(var e in u)if(u.hasOwnProperty(e)){var t=u[e];v.x=t.position.from.x,v.y=t.position.from.y,p.x=t.position.to.x,p.y=t.position.to.y,d(t,v,p,t.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):i=e),t},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(g).extend(),g},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,d=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(d.x)+" "+Math.round(d.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),l=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),v=new Float32Array(h),p=new Uint32Array(h),m=0,g=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(p),v=t,p=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(l,d),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;v[n*f]=t.x,v[n*f+1]=t.y,v[n*f+2]=e.size,p[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(p,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,d=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),v=0,p=new ArrayBuffer(16*d),m=new Float32Array(p),g=new Uint32Array(p),y=function(){if((v+1)*d>p.byteLength){var e=new ArrayBuffer(2*p.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,p=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,l),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),v+=1,o=e.id},removeLink:function(e){v>0&&(v-=1),v>e.id&&v>0&&r.copyArrayPart(g,e.id*c,v*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,p,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*v),o=v-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},d=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},l=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},v=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},p=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=l(e),o={offset:e};r.textureNumber>=s.length&&d();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=l(t.offset),r=l(o);p(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],v(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){v(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,d=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),l=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,v=0,p=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(l,d),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;p[n]=t.x-e.size,p[n+1]=t.y-e.size,p[n+2]=4*e._offset,p[n+3]=t.x+e.size,p[n+4]=t.y-e.size,p[n+5]=4*e._offset+1,p[n+6]=t.x-e.size,p[n+7]=t.y+e.size,p[n+8]=4*e._offset+2,p[n+9]=t.x-e.size,p[n+10]=t.y+e.size,p[n+11]=4*e._offset+2,p[n+12]=t.x+e.size,p[n+13]=t.y-e.size,p[n+14]=4*e._offset+1,p[n+15]=t.x+e.size,p[n+16]=t.y+e.size,p[n+17]=4*e._offset+3},createNode:function(t){p=i.extendArray(p,v,c),v+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){v>0&&(v-=1),v>t.id&&v>0&&(t.src&&e.remove(t.src),i.copyArrayPart(p,t.id*c,v*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,p,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*v)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f,c=0,d=0,l=[],h=[],v={},p={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(a),g.updateTransform(a)},V=function(){a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},P=function(e){e.fire("rescaled")},N={getLinkUI:function(e){return p[e]},getNodeUI:function(e){return v[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return u=e,this},placeLink:function(e){return s=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){d>0&&m.render(),c>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(){b()},addLink:function(e,t){var n=d++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,p[e.id]=r,r},addNode:function(e,t){var n=c++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),l[n]=r,v[e.id]=r,r},translateRel:function(e,t){a[12]+=2*a[0]*e/i/a[0],a[13]-=2*a[5]*t/o/a[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=a[12],r-=a[13],a[12]+=n*(1-e),a[13]+=r*(1-e),a[0]*=e,a[5]*=e,w(),P(this),a[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var s="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(s),s}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof f&&f(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){d>0&&(d-=1);var t=p[e.id];delete p[e.id],m.removeLink(t);var n=t.id;if(d>n){if(0===d||d===n)return;var r=h[d];h[n]=r,r.id=n}},releaseNode:function(e){c>0&&(c-=1);var t=v[e.id];delete v[e.id],g.removeNode(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=l[c];l[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;c>t;++t){var n=l[t];e.x=n.position.x,e.y=-n.position.y,u&&u(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;d>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,s&&s(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):f=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-a[12])/a[0],e.y=(e.y-a[13])/a[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;c>n;++n)if(t(l[n],e.x,e.y))return l[n].node;return null}};return Viva.Graph.Utils.events(N).extend(),N},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},i=function(t){return e.getNodeAtClientPos(t,r)},o=null,a=[],u=[],s=[],f=[],c=[],d=[],l=[],h=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},p=function(e){return v(e),!1},m=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(e){var r={x:0,y:0},g=null,y=+new Date,x=function(e){m(c,[g,e]),r.x=e.clientX,r.y=e.clientY},w=function(){h.stop("mousemove",x),h.stop("mouseup",w)},V=function(){n=e.getBoundingClientRect()};window.addEventListener("resize",V),V(),e.addEventListener("mousemove",function(e){if(!o){var t,s=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,t=i(r),t&&g!==t?(g=t,s=s||m(a,[g])):null===t&&g!==t&&(s=s||m(u,[g]),g=null),s&&v(e)}}),e.addEventListener("mousedown",function(e){var o,a=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]?(a=m(s,o),h.on("mousemove",x),h.on("mouseup",w),t=window.document.onselectstart,window.document.onselectstart=p,g=o[0]):g=null,a&&v(e)}),e.addEventListener("mouseup",function(e){var o,a=+new Date;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]&&(window.document.onselectstart=t,400>a-y&&o[0]===g?m(l,o):m(d,o),y=a,m(f,o)&&v(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&l.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file diff --git a/src/View/webglGraphics.js b/src/View/webglGraphics.js index d56b9bb..a8ee4ba 100644 --- a/src/View/webglGraphics.js +++ b/src/View/webglGraphics.js @@ -186,7 +186,7 @@ Viva.Graph.View.webglGraphics = function (options) { links[srcLinkId].id = srcLinkId; } }, -/*jshint unused: false */ + /** * Sets translate operation that should be applied to all nodes and links. */ diff --git a/src/version.js b/src/version.js index 4c3129a..5088e05 100644 --- a/src/version.js +++ b/src/version.js @@ -1 +1 @@ -Viva.Graph.version = '0.5.2'; +Viva.Graph.version = '0.5.3'; From 14137d7ab81bb5f3831176b9dae68b0ea607003e Mon Sep 17 00:00:00 2001 From: Balamurugan Soundararaj Date: Tue, 11 Feb 2014 15:59:45 +0000 Subject: [PATCH 061/276] Density function for a directed graph by default. Extended the function to give density for a directed graph (since the library usually creates directed graphs. If specifically needed the a true value can be passed to the function which will return the value for an undirected graph. --- src/Core/operations.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/Core/operations.js b/src/Core/operations.js index da6454e..194ace7 100644 --- a/src/Core/operations.js +++ b/src/Core/operations.js @@ -16,13 +16,25 @@ Viva.Graph.operations = function () { * * @returns density of the graph if graph has nodes. NaN otherwise */ - density : function (graph) { + + /* + * Extended the function to give density for a directed graph (since the library usually creates directed graphs) + * If specifically needed the a true value can be passed to the function which will return the value for + * a undirected graph. + * + * I am planning to implement a direced - undirected character to the graphs and expand this operations sections. + * --Bala. + */ + density : function (graph,undirected) { var nodes = graph.getNodesCount(); if (nodes === 0) { return NaN; } - - return 2 * graph.getLinksCount() / (nodes * (nodes - 1)); + if(undirected){ + return 2 * graph.getLinksCount() / (nodes * (nodes - 1)); + } else { + return 2 * graph.getLinksCount() / (nodes * (nodes - 1)); + } } }; }; From 73fdf6cdd0c7af6ccecf558048aebe1bb27681d8 Mon Sep 17 00:00:00 2001 From: Balamurugan Soundararaj Date: Tue, 11 Feb 2014 17:17:52 +0000 Subject: [PATCH 062/276] stupid mistake corrected the stupid mistake. --- src/Core/operations.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/operations.js b/src/Core/operations.js index 194ace7..9166802 100644 --- a/src/Core/operations.js +++ b/src/Core/operations.js @@ -33,7 +33,7 @@ Viva.Graph.operations = function () { if(undirected){ return 2 * graph.getLinksCount() / (nodes * (nodes - 1)); } else { - return 2 * graph.getLinksCount() / (nodes * (nodes - 1)); + return graph.getLinksCount() / (nodes * (nodes - 1)); } } }; From 80784e4de3fb12bd2c279f12d3c8379786073536 Mon Sep 17 00:00:00 2001 From: Sylvain GERARD Date: Wed, 19 Feb 2014 11:25:26 +0100 Subject: [PATCH 063/276] Implement center on position when using WebGL rendering --- dist/vivagraph.js | 11 +++++++++-- dist/vivagraph.min.js | 4 ++-- src/View/webglGraphics.js | 11 +++++++++-- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 6f83ec6..8b35745 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -5846,7 +5846,12 @@ Viva.Graph.View.webglGraphics = function (options) { height, nodesCount = 0, linksCount = 0, - transform, + transform = [ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + ], userPlaceNodeCallback, userPlaceLinkCallback, nodes = [], @@ -6001,7 +6006,9 @@ Viva.Graph.View.webglGraphics = function (options) { * Sets translate operation that should be applied to all nodes and links. */ graphCenterChanged : function (x, y) { - updateSize(); + transform[12] = (2 * x / width) - 1; + transform[13] = 1 - (2 * y / height); + updateTransformUniform(); }, /** diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 1ac503c..5272cbf 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.3",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},P=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},N=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",P,!1):e.addEventListener("DOMMouseScroll",P,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",P,!1):e.removeEventListener("DOMMouseScroll",P,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),N(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,d=Math.sqrt(f*f+c*c);d>r&&(u.velocity.x=r*f/d,u.velocity.y=r*c/d),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};r="number"==typeof r?r:1;var o=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,r);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){var n=.001;if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02,springTransform:function(){},timeStep:20});var r=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),i=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),o=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),a=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),u=new Viva.Graph.Rect,s=Viva.random("ted.com",103,114,101,97,116),f={},c=function(e){if(e.position)return e.position;var n=(u.x1+u.x2)/2,r=(u.y1+u.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],a=o.fromId!==e.id?f[o.fromId]:f[o.toId];a&&a.location&&(n=a.location.x,r=a.location.y)}return{x:n+s.next(i)-i/2,y:r+s.next(i)-i/2}},d=function(e){return f[e]},l=function(e){f[e]=null,delete f[e]},h={},v=function(t){var n=d(t);n.mass=1+e.getLinks(t).length/3},p=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},m=function(e){return e.isPinned},g=function(t){var n=d(t);if(!n){var i=e.getNode(t);if(!i)return;n=new Viva.Graph.Physics.Body,f[t]=n;var o=c(i);n.loc(o),v(t),p(i)&&(n.isPinned=!0),r.addBody(n)}},y=function(e){g(e.id)},x=function(t){var n=d(t.id);n&&(l(t.id),r.removeBody(n),0===e.getNodesCount()&&(u.x1=u.y1=0,u.x2=u.y2=0))},w=function(e){v(e.fromId),v(e.toId);var n=d(e.fromId),i=d(e.toId),o=r.addSpring(n,i,-1,e.weight);t.springTransform(e,o),h[e.id]=o},V=function(t){var n=h[t.id];if(n){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&v(i.id),o&&v(o.id),delete h[t.id],r.removeSpring(n)}},b=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&g(n.node.id),n.link&&w(n.link)):"remove"===n.changeType&&(n.node&&x(n.node),n.link&&V(n.link))}},P=function(){e.forEachNode(y),e.forEachLink(w),e.addEventListener("changed",b)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in f)if(f.hasOwnProperty(o)){var a=f[o];m(a)?(a.location.x=a.prevLocation.x,a.location.y=a.prevLocation.y):(a.prevLocation.x=a.location.x,a.prevLocation.y=a.location.y),t>a.location.x&&(t=a.location.x),a.location.x>r&&(r=a.location.x),n>a.location.y&&(n=a.location.y),a.location.y>i&&(i=a.location.y)}u.x1=t,u.x2=r,u.y1=n,u.y2=i}};return r.setSpringForce(o),r.setNbodyForce(i),r.setDragForce(a),P(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=r.run(t.timeStep);return N(),n>e},isNodePinned:function(e){var t=d(e.id);return t?m(t):void 0},pinNode:function(e,t){var n=d(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=d(e);return t||(g(e),t=d(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=d(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return u},dispose:function(){e.removeEventListener("change",b)},springLength:function(e){return 1===arguments.length?(o.options({length:e}),this):o.options().length},springCoeff:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff},gravity:function(e){return 1===arguments.length?(i.options({gravity:e}),this):i.options().gravity},theta:function(e){return 1===arguments.length?(i.options({theta:e}),this):i.options().theta},drag:function(e){return 1===arguments.length?(a.options({coeff:e}),this):a.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a={},u=function(e){e&&(a[e.id]||(a[e.id]=i(e)),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&u(n.node)}};return{run:function(){this.step()},step:function(){return s(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,d=!0,l=0,h=0,v=!1,p=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return v=u.step()&&!p,V(),!v},P=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(l=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},N=function(){v=!1,i.restart()},E=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX,g.offsetY),d=!1},L=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),p=!0,N()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),p=!0,V()},onStop:function(){u.pinNode(e,t),p=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),d&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(d=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},D=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);N()},R=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",D),o=null)},z=function(e,t){if(!t){var n=Viva.Graph.Utils.getDimension(f);t={x:n.width/2,y:n.height/2}}var r=Math.pow(1.4,e?-.2:.2);g.scale=s.scale(r,t),V(),w.fire("scale",g.scale)},B=function(){x.on("resize",R),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){z(0>t,n)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",D)},Y=function(){c=!1,O(),F(),x.stop("resize",R),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),E(),G(),C(),B(),c=!0),P(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},zoomOut:function(){z(!0)},zoomIn:function(){z(!1)},moveTo:function(e,t){s.graphCenterChanged(g.offsetX-e*g.scale,g.offsetY-t*g.scale),V()},getGraphics:function(){return s},dispose:function(){Y()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph(); -for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},d=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},l=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?d(e):(d=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,l()},translateRel:function(e,r){t+=e,n+=r,l()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,l()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),d=f.attr("id"),l=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&d===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&l===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i,o=1,a={},u={},s=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},f=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},c=function(){return Viva.Graph.svg("line").attr("stroke","#999")},d=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},l=function(e){e.fire("rescaled")},h={x:0,y:0},v={x:0,y:0},p={x:0,y:0},m=function(){if(e){var t="matrix("+o+", 0, 0,"+o+","+n+","+r+")";e.attr("transform",t)}},g={getNodeUI:function(e){return a[e]},getLinkUI:function(e){return u[e]},node:function(e){return"function"==typeof e?(s=e,this):void 0},link:function(e){return"function"==typeof e?(c=e,this):void 0},placeNode:function(e){return f=e,this},placeLink:function(e){return d=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,m()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(i,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(i).translate(-u.x,-u.y),f=e.getCTM().multiply(s);o=f.a,n=f.e,r=f.f;var c="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",c),l(this),o},resetScale:function(){o=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),l(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),m(),"function"==typeof i&&i(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(t,n){var r=c(t);if(r)return r.position=n,r.link=t,u[t.id]=r,e.childElementCount>0?e.insertBefore(r,e.firstChild):e.appendChild(r),r},releaseLink:function(t){var n=u[t.id];n&&(e.removeChild(n),delete u[t.id])},addNode:function(t,n){var r=s(t);if(r)return r.position=n,r.node=t,a[t.id]=r,e.appendChild(r),r},releaseNode:function(t){var n=a[t.id];n&&(e.removeChild(n),delete a[t.id])},renderNodes:function(){for(var e in a)if(a.hasOwnProperty(e)){var t=a[e];h.x=t.position.x,h.y=t.position.y,f(t,h,t.node)}},renderLinks:function(){for(var e in u)if(u.hasOwnProperty(e)){var t=u[e];v.x=t.position.from.x,v.y=t.position.from.y,p.x=t.position.to.x,p.y=t.position.to.y,d(t,v,p,t.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):i=e),t},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(g).extend(),g},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,d=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(d.x)+" "+Math.round(d.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),l=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),v=new Float32Array(h),p=new Uint32Array(h),m=0,g=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(p),v=t,p=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(l,d),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;v[n*f]=t.x,v[n*f+1]=t.y,v[n*f+2]=e.size,p[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(p,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,d=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),v=0,p=new ArrayBuffer(16*d),m=new Float32Array(p),g=new Uint32Array(p),y=function(){if((v+1)*d>p.byteLength){var e=new ArrayBuffer(2*p.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,p=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,l),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),v+=1,o=e.id},removeLink:function(e){v>0&&(v-=1),v>e.id&&v>0&&r.copyArrayPart(g,e.id*c,v*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,p,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*v),o=v-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},d=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},l=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},v=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},p=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=l(e),o={offset:e};r.textureNumber>=s.length&&d();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=l(t.offset),r=l(o);p(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],v(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){v(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,d=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),l=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,v=0,p=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(l,d),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;p[n]=t.x-e.size,p[n+1]=t.y-e.size,p[n+2]=4*e._offset,p[n+3]=t.x+e.size,p[n+4]=t.y-e.size,p[n+5]=4*e._offset+1,p[n+6]=t.x-e.size,p[n+7]=t.y+e.size,p[n+8]=4*e._offset+2,p[n+9]=t.x-e.size,p[n+10]=t.y+e.size,p[n+11]=4*e._offset+2,p[n+12]=t.x+e.size,p[n+13]=t.y-e.size,p[n+14]=4*e._offset+1,p[n+15]=t.x+e.size,p[n+16]=t.y+e.size,p[n+17]=4*e._offset+3},createNode:function(t){p=i.extendArray(p,v,c),v+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){v>0&&(v-=1),v>t.id&&v>0&&(t.src&&e.remove(t.src),i.copyArrayPart(p,t.id*c,v*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,p,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*v)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f,c=0,d=0,l=[],h=[],v={},p={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(a),g.updateTransform(a)},V=function(){a=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},P=function(e){e.fire("rescaled")},N={getLinkUI:function(e){return p[e]},getNodeUI:function(e){return v[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return u=e,this},placeLink:function(e){return s=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){d>0&&m.render(),c>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(){b()},addLink:function(e,t){var n=d++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,p[e.id]=r,r},addNode:function(e,t){var n=c++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),l[n]=r,v[e.id]=r,r},translateRel:function(e,t){a[12]+=2*a[0]*e/i/a[0],a[13]-=2*a[5]*t/o/a[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=a[12],r-=a[13],a[12]+=n*(1-e),a[13]+=r*(1-e),a[0]*=e,a[5]*=e,w(),P(this),a[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var s="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(s),s}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof f&&f(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){d>0&&(d-=1);var t=p[e.id];delete p[e.id],m.removeLink(t);var n=t.id;if(d>n){if(0===d||d===n)return;var r=h[d];h[n]=r,r.id=n}},releaseNode:function(e){c>0&&(c-=1);var t=v[e.id];delete v[e.id],g.removeNode(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=l[c];l[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;c>t;++t){var n=l[t];e.x=n.position.x,e.y=-n.position.y,u&&u(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;d>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,s&&s(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):f=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-a[12])/a[0],e.y=(e.y-a[13])/a[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;c>n;++n)if(t(l[n],e.x,e.y))return l[n].node;return null}};return Viva.Graph.Utils.events(N).extend(),N},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},i=function(t){return e.getNodeAtClientPos(t,r)},o=null,a=[],u=[],s=[],f=[],c=[],d=[],l=[],h=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},p=function(e){return v(e),!1},m=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(e){var r={x:0,y:0},g=null,y=+new Date,x=function(e){m(c,[g,e]),r.x=e.clientX,r.y=e.clientY},w=function(){h.stop("mousemove",x),h.stop("mouseup",w)},V=function(){n=e.getBoundingClientRect()};window.addEventListener("resize",V),V(),e.addEventListener("mousemove",function(e){if(!o){var t,s=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,t=i(r),t&&g!==t?(g=t,s=s||m(a,[g])):null===t&&g!==t&&(s=s||m(u,[g]),g=null),s&&v(e)}}),e.addEventListener("mousedown",function(e){var o,a=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]?(a=m(s,o),h.on("mousemove",x),h.on("mouseup",w),t=window.document.onselectstart,window.document.onselectstart=p,g=o[0]):g=null,a&&v(e)}),e.addEventListener("mouseup",function(e){var o,a=+new Date;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]&&(window.document.onselectstart=t,400>a-y&&o[0]===g?m(l,o):m(d,o),y=a,m(f,o)&&v(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&l.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file +var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.3",Viva.lazyExtend=function(a,b){var c;if(a||(a={}),b)for(c in b)if(b.hasOwnProperty(c)){var d=a.hasOwnProperty(c),e=typeof b[c],f=!d||typeof a[c]!==e;f?a[c]=b[c]:"object"===e&&(a[c]=Viva.lazyExtend(a[c],b[c]))}return a},Viva.random=function(){var a,b=arguments[0];a="number"==typeof b?b:"string"==typeof b?b.length:+new Date;var c=function(){return a=a+2127912214+(a<<12)&4294967295,a=4294967295&(3345072700^a^a>>>19),a=a+374761393+(a<<5)&4294967295,a=4294967295&(a+3550635116^a<<9),a=a+4251993797+(a<<3)&4294967295,a=4294967295&(3042594569^a^a>>>16),(268435455&a)/268435456};return{next:function(a){return Math.floor(c()*a)},nextDouble:function(){return c()}}},Viva.randomIterator=function(a,b){return b=b||Viva.random(),{forEach:function(c){var d,e,f;for(d=a.length-1;d>0;--d)e=b.next(d+1),f=a[e],a[e]=a[d],a[d]=f,c(f);a.length&&c(a[0])},shuffle:function(){var c,d,e;for(c=a.length-1;c>0;--c)d=b.next(c+1),e=a[d],a[d]=a[c],a[c]=e;return a}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var a=window.navigator.userAgent.toLowerCase(),b=/(webkit)[ \/]([\w.]+)/,c=/(opera)(?:.*version)?[ \/]([\w.]+)/,d=/(msie) ([\w.]+)/,e=/(mozilla)(?:.*? rv:([\w.]+))?/,f=b.exec(a)||c.exec(a)||d.exec(a)||a.indexOf("compatible")<0&&e.exec(a)||[];return{browser:f[1]||"",version:f[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(a,b){if(b.indexOf)return b.indexOf(a);var c,d=b.length;for(c=0;d>c;c+=1)if(b.hasOwnProperty(c)&&b[c]===a)return c;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(a){if(!a)throw{message:"Cannot get dimensions of undefined container"};var b=a.clientWidth,c=a.clientHeight;return{left:0,top:0,width:b,height:c}},Viva.Graph.Utils.findElementPosition=function(a){var b=0,c=0;if(a.offsetParent)do b+=a.offsetLeft,c+=a.offsetTop;while(null!==(a=a.offsetParent));return[b,c]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(a){var b=function(a){var b={};return a.fire=function(a,c){var d,e,f,g;if("string"!=typeof a)throw"Only strings can be used as even type";if(b.hasOwnProperty(a))for(d=b[a],g=0;gc?d=-1:c>o&&(d=1),e(a,d,{x:a.touches[0].clientX,y:a.touches[0].clientY}),o=c,r(a),s(a)}},B=function(a){n=!1,i.stop("touchmove",A),i.stop("touchend",B),i.stop("touchcancel",B),h=null,d&&d(a)},C=function(a,c){r(a),s(a),l=c.clientX,m=c.clientY,h=a.target||a.srcElement,b&&b(a,{x:l,y:m}),n||(n=!0,i.on("touchmove",A),i.on("touchend",B),i.on("touchcancel",B))},D=function(b){return console.log("Touch start for ",a),1===b.touches.length?C(b,b.touches[0]):void(2===b.touches.length&&(r(b),s(b),o=z(b.touches[0],b.touches[1])))};return j.on("mousedown",v),j.on("touchstart",D),{onStart:function(a){return b=a,this},onDrag:function(a){return c=a,this},onStop:function(a){return d=a,this},onScroll:function(a){return y(a),this},release:function(){i.stop("mousemove",u),i.stop("mousedown",v),i.stop("mouseup",w),i.stop("touchmove",A),i.stop("touchend",B),i.stop("touchcancel",B),y(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(a,b){var c={};return{bindDragNDrop:function(a,d){var e;if(d){var f=b.getNodeUI(a.id);e=Viva.Graph.Utils.dragndrop(f),"function"==typeof d.onStart&&e.onStart(d.onStart),"function"==typeof d.onDrag&&e.onDrag(d.onDrag),"function"==typeof d.onStop&&e.onStop(d.onStop),c[a.id]=e}else(e=c[a.id])&&(e.release(),delete c[a.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var a,b,c=0,d=["ms","moz","webkit","o"];for(b="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},a=0;a=0==r>=4?null:(j=h-f,l=e-g,n=g*f-e*h,o=j*a+l*b+n,p=j*c+l*d+n,0!==o&&0!==p&&o>=0==p>=0?null:(s=i*l-j*k,0===s?null:(t=0>s?-s/2:s/2,t=0,u=k*n-l*m,v.x=(0>u?u-t:u+t)/s,u=j*m-i*n,v.y=(0>u?u-t:u+t)/s,v)))},intersectRect:function(a,b,c,d,e,f,g,h){return this.intersect(a,b,a,d,e,f,g,h)||this.intersect(a,d,c,d,e,f,g,h)||this.intersect(c,d,c,b,e,f,g,h)||this.intersect(c,b,a,b,e,f,g,h)},convexHull:function(a){var b=function(a,b){var c,d,e=function(b){var c=b.x-a.x,d=b.y-a.y,e=c>0?1:-1;return e*c*c/(c*c+d*d)},f=b.sort(function(a,b){return e(b)-e(a)}),g=f[0],h=e(g),i=g.x-a.x,j=g.y-a.y,k=i*i+j*j;for(d=1;dc?f.splice(d,1):f.splice(d-1,1)):h=l}return f},c=function(a,b,c){return(c.x-a.x)*(b.y-a.y)-(c.y-a.y)*(b.x-a.x)<0};if(a.length<3)return a;var d,e=0;for(d=0;d0&&(g(a),f.length=0)},j=function(a,b){f.push({node:a,changeType:b})},k=function(a,b){f.push({link:a,changeType:b})},l={addNode:function(b,c){if("undefined"==typeof b)throw{message:"Invalid node identifier"};h();var e=this.getNode(b);return e?j(e,"update"):(e=new Viva.Graph.Node(b),d++,j(e,"add")),e.data=c,a[b]=e,i(this),e},addLink:function(a,d,e){h();var f=this.getNode(a)||this.addNode(a),g=this.getNode(d)||this.addNode(d),j=a.toString()+"👉 "+d.toString(),l=c.hasOwnProperty(j);(l||this.hasLink(a,d))&&(l||(c[j]=0),j+="@"+ ++c[j]);var m=new Viva.Graph.Link(a,d,e,j);return b.push(m),f.links.push(m),g.links.push(m),k(m,"add"),i(this),m},removeLink:function(a){if(!a)return!1;var c=Viva.Graph.Utils.indexOfElementInArray(a,b);if(0>c)return!1;h(),b.splice(c,1);var d=this.getNode(a.fromId),e=this.getNode(a.toId);return d&&(c=Viva.Graph.Utils.indexOfElementInArray(a,d.links),c>=0&&d.links.splice(c,1)),e&&(c=Viva.Graph.Utils.indexOfElementInArray(a,e.links),c>=0&&e.links.splice(c,1)),k(a,"remove"),i(this),!0},removeNode:function(b){var c=this.getNode(b);if(!c)return!1;for(h();c.links.length;){var e=c.links[0];this.removeLink(e)}a[b]=null,delete a[b],d--,j(c,"remove"),i(this)},getNode:function(b){return a[b]},getNodesCount:function(){return d},getLinksCount:function(){return b.length},getLinks:function(a){var b=this.getNode(a);return b?b.links:null},forEachNode:function(b){if("function"==typeof b){var c;for(c in a)if(a.hasOwnProperty(c)&&b(a[c]))return}},forEachLinkedNode:function(b,c,d){var e,f,g,h=this.getNode(b);if(h&&h.links&&"function"==typeof c)if(d)for(e=0;ec;++c)a(b[c])},beginUpdate:function(){h()},endUpdate:function(){i(this)},clear:function(){var a=this;a.beginUpdate(),a.forEachNode(function(b){a.removeNode(b.id)}),a.endUpdate()},hasLink:function(a,b){var c,d=this.getNode(a);if(!d)return null;for(c=0;cc;++c){var h=a.bodies[c],i=b/h.mass;h.velocity.x+=i*h.force.x,h.velocity.y+=i*h.force.y;var j=h.velocity.x,k=h.velocity.y,l=Math.sqrt(j*j+k*k);l>d&&(h.velocity.x=d*j/l,h.velocity.y=d*k/l),e=b*h.velocity.x,f=b*h.velocity.y,h.location.x+=e,h.location.y+=f}return e*e+f*f}}},Viva.Graph.Physics.nbodyForce=function(a){function b(a,b){this.node=a,this.body=b}function c(){this.stack=[],this.popIdx=0}a=Viva.lazyExtend(a||{gravity:-1,theta:.8}),c.prototype={isEmpty:function(){return 0===this.popIdx},push:function(a,c){var d=this.stack[this.popIdx];d?(d.node=a,d.body=c):this.stack[this.popIdx]=new b(a,c),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var d=a.gravity,e=[],f=new c,g=a.theta,h=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),i=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},j=[],k=0,l=function(){var a;return j[k]?(a=j[k],a.quads[0]=null,a.quads[1]=null,a.quads[2]=null,a.quads[3]=null,a.body=null,a.mass=a.massX=a.massY=0,a.left=a.right=a.top=a.bottom=0,a.isInternal=!1):(a=new i,j[k]=a),++k,a},m=l(),n=function(a,b){var c=Math.abs(a.x-b.x),d=Math.abs(a.y-b.y);return 1e-8>c&&1e-8>d},o=function(a){for(f.reset(),f.push(m,a);!f.isEmpty();){var b=f.pop(),c=b.node,d=b.body;if(c.isInternal){var e=d.location.x,g=d.location.y;c.mass=c.mass+d.mass,c.massX=c.massX+d.mass*e,c.massY=c.massY+d.mass*g;var i=0,j=c.left,k=(c.right+j)/2,o=c.top,p=(c.bottom+o)/2;if(e>k){i+=1;var q=j;j=k,k+=k-q}if(g>p){i+=2;var r=o;o=p,p+=p-r}var s=c.quads[i];s||(s=l(),s.left=j,s.top=o,s.right=k,s.bottom=p,c.quads[i]=s),f.push(s,d)}else if(c.body){var t=c.body;if(c.body=null,c.isInternal=!0,n(t.location,d.location)){if(c.right-c.left<1e-8)return;do{var u=h.nextDouble(),v=(c.right-c.left)*u,w=(c.bottom-c.top)*u;t.location.x=c.left+v,t.location.y=c.top+w}while(n(t.location,d.location))}f.push(c,t),f.push(c,d)}else c.body=d}},p=function(a){var b,c,f,i,j=e,k=1,l=0,n=1;for(j[0]=m;k;){var o=j[l],p=o.body;k-=1,l+=1,p&&p!==a?(c=p.location.x-a.location.x,f=p.location.y-a.location.y,i=Math.sqrt(c*c+f*f),0===i&&(c=(h.nextDouble()-.5)/50,f=(h.nextDouble()-.5)/50,i=Math.sqrt(c*c+f*f)),b=d*p.mass*a.mass/(i*i*i),a.force.x=a.force.x+b*c,a.force.y=a.force.y+b*f):(c=o.massX/o.mass-a.location.x,f=o.massY/o.mass-a.location.y,i=Math.sqrt(c*c+f*f),0===i&&(c=(h.nextDouble()-.5)/50,f=(h.nextDouble()-.5)/50,i=Math.sqrt(c*c+f*f)),(o.right-o.left)/ii&&(c=i),i>e&&(e=i),d>j&&(d=j),j>f&&(f=j)}var n=e-c,p=f-d;for(n>p?f=d+n:e=c+p,k=0,m=l(),m.left=c,m.right=e,m.top=d,m.bottom=f,b=h;b--;)o(g[b],m)};return{insert:o,init:q,update:p,options:function(a){return a?("number"==typeof a.gravity&&(d=a.gravity),"number"==typeof a.theta&&(g=a.theta),this):{gravity:d,theta:g}}}},Viva.Graph.Physics.dragForce=function(a){a||(a={});var b={coeff:a.coeff||.01};return{update:function(a){a.force.x-=b.coeff*a.velocity.x,a.force.y-=b.coeff*a.velocity.y},options:function(a){return a?("number"==typeof a.coeff&&(b.coeff=a.coeff),this):b}}},Viva.Graph.Physics.springForce=function(a){a=Viva.lazyExtend(a,{length:50,coeff:22e-5});var b=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(c){var d=c.body1,e=c.body2,f=c.length<0?a.length:c.length,g=e.location.x-d.location.x,h=e.location.y-d.location.y,i=Math.sqrt(g*g+h*h);0===i&&(g=(b.nextDouble()-.5)/50,h=(b.nextDouble()-.5)/50,i=Math.sqrt(g*g+h*h));var j=i-f,k=(!c.coeff||c.coeff<0?a.coeff:c.coeff)*j/i*c.weight;d.force.x+=k*g,d.force.y+=k*h,e.force.x+=-k*g,e.force.y+=-k*h},options:function(b){return b?("number"==typeof b.length&&(a.length=b.length),"number"==typeof b.coeff&&(a.coeff=b.coeff),this):a}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(a){var b,c,d,e=a,f=[],g=[];return{speedLimit:1,bodies:f,accumulate:function(){var a,e;for(c.init(this),a=f.length;a--;)e=f[a],e.force.x=0,e.force.y=0,c.update(e),d.update(e);for(a=g.length;a--;)b.update(g[a])},run:function(a){return this.accumulate(),e.integrate(this,a)},addBody:function(a){if(!a)throw{message:"Cannot add null body to force simulator"};return f.push(a),a},removeBody:function(a){if(!a)return!1;var b=Viva.Graph.Utils.indexOfElementInArray(a,f);return 0>b?!1:f.splice(b,1)},addSpring:function(a,b,c,d,e){if(!a||!b)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof c)throw{message:"Spring length should be a number"};d="number"==typeof d?d:1;var f=new Viva.Graph.Physics.Spring(a,b,c,e>=0?e:-1,d);return g.push(f),f},removeSpring:function(a){if(!a)return!1;var b=Viva.Graph.Utils.indexOfElementInArray(a,g);return 0>b?!1:g.splice(b,1)},setNbodyForce:function(a){if(!a)throw{message:"Cannot add mighty (unknown) force to the simulator"};c=a},setDragForce:function(a){if(!a)throw{message:"Cannot add mighty (unknown) force to the simulator"};d=a},setSpringForce:function(a){if(!a)throw{message:"Cannot add unknown force to the simulator"};b=a}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(a,b){var c=.001;if(!a)throw{message:"Graph structure cannot be undefined"};b=Viva.lazyExtend(b,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02,springTransform:function(){},timeStep:20});var d=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),e=Viva.Graph.Physics.nbodyForce({gravity:b.gravity,theta:b.theta}),f=Viva.Graph.Physics.springForce({length:b.springLength,coeff:b.springCoeff}),g=Viva.Graph.Physics.dragForce({coeff:b.dragCoeff}),h=new Viva.Graph.Rect,i=Viva.random("ted.com",103,114,101,97,116),j={},k=function(a){if(a.position)return a.position;var c=(h.x1+h.x2)/2,d=(h.y1+h.y2)/2,e=b.springLength;if(a.links&&a.links.length>0){var f=a.links[0],g=f.fromId!==a.id?j[f.fromId]:j[f.toId];g&&g.location&&(c=g.location.x,d=g.location.y)}return{x:c+i.next(e)-e/2,y:d+i.next(e)-e/2}},l=function(a){return j[a]},m=function(a){j[a]=null,delete j[a]},n={},o=function(b){var c=l(b);c.mass=1+a.getLinks(b).length/3},p=function(a){return a&&(a.isPinned||a.data&&a.data.isPinned)},q=function(a){return a.isPinned},r=function(b){var c=l(b);if(!c){var e=a.getNode(b);if(!e)return;c=new Viva.Graph.Physics.Body,j[b]=c;var f=k(e);c.loc(f),o(b),p(e)&&(c.isPinned=!0),d.addBody(c)}},s=function(a){r(a.id)},t=function(b){var c=l(b.id);c&&(m(b.id),d.removeBody(c),0===a.getNodesCount()&&(h.x1=h.y1=0,h.x2=h.y2=0))},u=function(a){o(a.fromId),o(a.toId);var c=l(a.fromId),e=l(a.toId),f=d.addSpring(c,e,-1,a.weight);b.springTransform(a,f),n[a.id]=f},v=function(b){var c=n[b.id];if(c){var e=a.getNode(b.fromId),f=a.getNode(b.toId);e&&o(e.id),f&&o(f.id),delete n[b.id],d.removeSpring(c)}},w=function(a){for(var b=0;bd&&(d=g.location.x),g.location.ye&&(e=g.location.y)}h.x1=b,h.x2=d,h.y1=c,h.y2=e}};return d.setSpringForce(f),d.setNbodyForce(e),d.setDragForce(g),x(),{run:function(a){var b;for(a=a||50,b=0;a>b;++b)this.step()},step:function(){var a=d.run(b.timeStep);return y(),c>a},isNodePinned:function(a){var b=l(a.id);return b?q(b):void 0},pinNode:function(a,b){var c=l(a.id);c.isPinned=!!b},getNodePosition:function(a){var b=l(a);return b||(r(a),b=l(a)),b&&b.location},getLinkPosition:function(a){var b=this.getNodePosition(a.fromId),c=this.getNodePosition(a.toId);return{from:b,to:c}},setNodePosition:function(a,b,c){var d=l(a.id);d&&(d.prevLocation.x=d.location.x=b,d.prevLocation.y=d.location.y=c)},getGraphRect:function(){return h},dispose:function(){a.removeEventListener("change",w)},springLength:function(a){return 1===arguments.length?(f.options({length:a}),this):f.options().length},springCoeff:function(a){return 1===arguments.length?(f.options({coeff:a}),this):f.options().coeff},gravity:function(a){return 1===arguments.length?(e.options({gravity:a}),this):e.options().gravity},theta:function(a){return 1===arguments.length?(e.options({theta:a}),this):e.options().theta},drag:function(a){return 1===arguments.length?(g.options({coeff:a}),this):g.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(a,b){b=Viva.lazyExtend(b,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var c=Viva.random(b.seed),d=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),e=function(){return new Viva.Graph.Point2d(c.next(b.maxX),c.next(b.maxY))},f=function(a,b){a.xb.x2&&(b.x2=a.x),a.yb.y2&&(b.y2=a.y)},g={},h=function(a){a&&(g[a.id]||(g[a.id]=e(a)),f(g[a.id],d))},i=function(){0!==a.getNodesCount()&&(d.x1=Number.MAX_VALUE,d.y1=Number.MAX_VALUE,d.x2=Number.MIN_VALUE,d.y2=Number.MIN_VALUE,a.forEachNode(h))},j=function(a){for(var b=0;b0)for(a=0;ab,c)}),a.forEachNode(F),O(),f=Viva.Graph.Utils.events(a),f.on("changed",L)},R=function(){k=!1,O(),N(),t.stop("resize",M),u.removeAllListeners(),e.stop(),a.forEachLink(function(a){b.renderLinks&&E(a)}),a.forEachNode(function(a){G(a),C(a)}),h.dispose(),I()};return{run:function(a){return k||(s(),z(),A(),H(),Q(),k=!0),x(a),this},reset:function(){i.resetScale(),A(),r.scale=1},pause:function(){e.stop()},resume:function(){e.restart()},rerender:function(){return v(),this},zoomOut:function(){P(!0)},zoomIn:function(){P(!1)},moveTo:function(a,b){i.graphCenterChanged(r.offsetX-a*r.scale,r.offsetY-b*r.scale),v()},getGraphics:function(){return i},dispose:function(){R()},on:function(a,b){return u.addEventListener(a,b),this},off:function(a,b){return u.removeEventListener(a,b),this}}},Viva.Graph.serializer=function(){var a=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},b=function(a){return{id:a.id,data:a.data}},c=function(a){return{fromId:a.fromId,toId:a.toId,data:a.data}},d=function(a){return a},e=function(a){return a};return{storeToJSON:function(d,e,f){if(!d)throw"Graph is not defined";a(),e=e||b,f=f||c;var g={nodes:[],links:[]};return d.forEachNode(function(a){g.nodes.push(e(a))}),d.forEachLink(function(a){g.links.push(f(a))}),JSON.stringify(g)},loadFromJSON:function(b,c,f){if("string"!=typeof b)throw"String expected in loadFromJSON() method";a(),c=c||d,f=f||e;var g,h=JSON.parse(b),i=Viva.Graph.graph();if(!h||!h.nodes||!h.links)throw"Passed json string does not represent valid graph";for(g=0;gc?void d.push({name:a,probability:e/b}):!0}),d},g=function(a){var b=[];return a.forEachNode(function(a){var c=Viva.Graph._community.occuranceMap(d);c.add(a.id),a.slpa={memory:c},b.push(a.id)}),b},h=function(a,c){var f,g=Viva.randomIterator(c,e),h=function(b){var c=a.getNode(b),e=Viva.Graph._community.occuranceMap(d);a.forEachLinkedNode(b,function(a){var b=a.slpa.memory.getRandomWord();e.add(b)});var f=e.getMostPopularFair();c.slpa.memory.add(f)};for(f=0;b-1>f;++f)g.forEach(h)},i=function(a){var d={};return a.forEachNode(function(a){var e,g=f(a.slpa.memory,c*b);for(e=0;ea?-1:a>c?1:0})},g=function(){d&&(f(),d=!1)};return{add:function(a){a=String(a),b.hasOwnProperty(a)?b[a]+=1:b[a]=1,c.push(a),d=!0},getWordCount:function(a){return b[a]||0},getMostPopularFair:function(){if(1===c.length)return c[0];g();var d,f=0;for(d=1;da)throw{message:"At least two nodes expected for complete graph"};var b,c,d=Viva.Graph.graph();for(d.Name="Complete K"+a,b=0;a>b;++b)for(c=b+1;a>c;++c)b!==c&&d.addLink(b,c);return d},completeBipartite:function(a,b){if(!a||!b||0>a||0>b)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var c,d,e=Viva.Graph.graph();for(e.Name="Complete K "+a+","+b,c=0;a>c;++c)for(d=a;a+b>d;++d)e.addLink(c,d);return e},ladder:function(a){if(!a||0>a)throw{message:"Invalid number of nodes"};var b,c=Viva.Graph.graph();for(c.Name="Ladder graph "+a,b=0;a-1>b;++b)c.addLink(b,b+1),c.addLink(a+b,a+b+1),c.addLink(b,a+b);return c.addLink(a-1,2*a-1),c},circularLadder:function(a){if(!a||0>a)throw{message:"Invalid number of nodes"};var b=this.ladder(a);return b.Name="Circular ladder graph "+a,b.addLink(0,a-1),b.addLink(a,2*a-1),b},grid:function(a,b){var c,d,e=Viva.Graph.graph(); +for(e.Name="Grid graph "+a+"x"+b,c=0;a>c;++c)for(d=0;b>d;++d){var f=c+d*a;c>0&&e.addLink(f,c-1+d*a),d>0&&e.addLink(f,c+(d-1)*a)}return e},path:function(a){if(!a||0>a)throw{message:"Invalid number of nodes"};var b,c=Viva.Graph.graph();for(c.Name="Path graph "+a,c.addNode(0),b=1;a>b;++b)c.addLink(b-1,b);return c},lollipop:function(a,b){if(!b||0>b||!a||0>a)throw{message:"Invalid number of nodes"};var c,d=this.complete(a);for(d.Name="Lollipop graph. Head x Path "+a+"x"+b,c=0;b>c;++c)d.addLink(a+c-1,a+c);return d},balancedBinTree:function(a){var b,c=Viva.Graph.graph(),d=Math.pow(2,a);for(c.Name="Balanced bin tree graph "+a,b=1;d>b;++b){var e=b,f=2*e,g=2*e+1;c.addLink(e,f),c.addLink(e,g)}return c},randomNoLinks:function(a){if(!a||0>a)throw{message:"Invalid number of nodes"};var b,c=Viva.Graph.graph();for(c.Name="Random graph, no Links: "+a,b=0;a>b;++b)c.addNode(b);return c}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var a,b,c,d="OLD_IE",e=1,f=1,g=function(){var a,b,c=Viva.BrowserInfo.browser;switch(c){case"mozilla":a="Moz";break;case"webkit":a="webkit";break;case"opera":a="O";break;case"msie":if(b=Viva.BrowserInfo.version.split(".")[0],!(b>8))return d;a="ms"}return a?a+"Transform":null}(),h=function(){return g===d?function(a,b,c,d){var e=Math.cos(d),f=Math.sin(d);0>d&&(d=2*Math.PI+d),d=n.byteLength){var a=new ArrayBuffer(2*n.byteLength),b=new Float32Array(a),c=new Uint32Array(a);c.set(p),o=b,p=c,n=a}};return{load:function(f){b=f,e=Viva.Graph.webgl(f),a=e.createProgram(m,l),b.useProgram(a),d=e.getLocations(a,["a_vertexPos","a_color","u_screenSize","u_transform"]),b.enableVertexAttribArray(d.vertexPos),b.enableVertexAttribArray(d.color),c=b.createBuffer()},position:function(a,b){var c=a.id;o[c*j]=b.x,o[c*j+1]=b.y,o[c*j+2]=a.size,p[c*j+3]=a.color},updateTransform:function(a){i=!0,h=a},updateSize:function(a,b){f=a,g=b,i=!0},removeNode:function(a){q>0&&(q-=1),a.id0&&e.copyArrayPart(p,a.id*j,q*j,j)},createNode:function(){r(),q+=1},replaceProperties:function(){},render:function(){b.useProgram(a),b.bindBuffer(b.ARRAY_BUFFER,c),b.bufferData(b.ARRAY_BUFFER,n,b.DYNAMIC_DRAW),i&&(i=!1,b.uniformMatrix4fv(d.transform,!1,h),b.uniform2f(d.screenSize,f,g)),b.vertexAttribPointer(d.vertexPos,3,b.FLOAT,!1,j*Float32Array.BYTES_PER_ELEMENT,0),b.vertexAttribPointer(d.color,4,b.UNSIGNED_BYTE,!0,j*Float32Array.BYTES_PER_ELEMENT,12),b.drawArrays(b.POINTS,0,q)}}},Viva.Graph.View.webglLinkProgram=function(){var a,b,c,d,e,f,g,h,i,j,k=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),m=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),n=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),o=0,p=new ArrayBuffer(16*l),q=new Float32Array(p),r=new Uint32Array(p),s=function(){if((o+1)*l>p.byteLength){var a=new ArrayBuffer(2*p.byteLength),b=new Float32Array(a),c=new Uint32Array(a);c.set(r),q=b,r=c,p=a}};return{load:function(f){b=f,d=Viva.Graph.webgl(f),a=d.createProgram(n,m),b.useProgram(a),e=d.getLocations(a,["a_vertexPos","a_color","u_screenSize","u_transform"]),b.enableVertexAttribArray(e.vertexPos),b.enableVertexAttribArray(e.color),c=b.createBuffer()},position:function(a,b,c){var d=a.id,e=d*k;q[e]=b.x,q[e+1]=b.y,r[e+2]=a.color,q[e+3]=c.x,q[e+4]=c.y,r[e+5]=a.color},createLink:function(a){s(),o+=1,f=a.id},removeLink:function(a){o>0&&(o-=1),a.id0&&d.copyArrayPart(r,a.id*k,o*k,k)},updateTransform:function(a){j=!0,i=a},updateSize:function(a,b){g=a,h=b,j=!0},render:function(){b.useProgram(a),b.bindBuffer(b.ARRAY_BUFFER,c),b.bufferData(b.ARRAY_BUFFER,p,b.DYNAMIC_DRAW),j&&(j=!1,b.uniformMatrix4fv(e.transform,!1,i),b.uniform2f(e.screenSize,g,h)),b.vertexAttribPointer(e.vertexPos,2,b.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),b.vertexAttribPointer(e.color,4,b.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),b.drawArrays(b.LINES,0,2*o),f=o-1},bringToFront:function(a){f>a.id&&d.swapArrayPart(q,a.id*k,f*k,k),f>0&&(f-=1)},getFrontLinkId:function(){return f}}},Viva.Graph.View.Texture=function(a){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=a},Viva.Graph.View.webglAtlas=function(a){var b,c,d=Math.sqrt(a||1024)<<0,e=d,f=1,g={},h=0,i=[],j=[],k=function(a){return 0===(a&a-1)},l=function(){var a=new Viva.Graph.View.Texture(d*e);i.push(a)},m=function(b){var c=b/a<<0,e=b%a,f=e/d<<0,g=e%d;return{textureNumber:c,row:f,col:g}},n=function(){c.isDirty=!0,h=0,b=null},o=function(){b&&(window.clearTimeout(b),h+=1,b=null),h>10?n():b=window.setTimeout(n,400)},p=function(a,b){var c=i[a.textureNumber].canvas,d=i[b.textureNumber].ctx,f=b.col*e,g=b.row*e;d.drawImage(c,a.col*e,a.row*e,e,e,f,g,e,e),i[a.textureNumber].isDirty=!0,i[b.textureNumber].isDirty=!0},q=function(a,b,c){var d=m(a),f={offset:a};d.textureNumber>=i.length&&l();var h=i[d.textureNumber];h.ctx.drawImage(b,d.col*e,d.row*e,e,e),j[a]=b.src,g[b.src]=f,h.isDirty=!0,c(f)};if(!k(a))throw"Tiles per texture should be power of two.";return c={isDirty:!1,clearDirty:function(){var a;for(this.isDirty=!1,a=0;a0&&(o-=1),b.id0&&(b.src&&a.remove(b.src),e.copyArrayPart(p,b.id*k,o*k,k))},replaceProperties:function(a,b){b._offset=a._offset},updateTransform:function(a){j=!0,i=a},updateSize:function(a,b){g=a,h=b,j=!0},render:function(){c.useProgram(b),c.bindBuffer(c.ARRAY_BUFFER,d),c.bufferData(c.ARRAY_BUFFER,p,c.DYNAMIC_DRAW),j&&(j=!1,c.uniformMatrix4fv(f.transform,!1,i),c.uniform2f(f.screenSize,g,h)),c.vertexAttribPointer(f.vertexPos,2,c.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),c.vertexAttribPointer(f.customAttributes,1,c.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),r(),c.drawArrays(c.TRIANGLES,0,6*o)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(a){a=Viva.lazyExtend(a,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var b,c,d,e,f,g,h,i,j=0,k=0,l=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],m=[],n=[],o={},p={},q=Viva.Graph.View.webglLinkProgram(),r=Viva.Graph.View.webglNodeProgram(),s=function(){return Viva.Graph.View.webglSquare()},t=function(){return Viva.Graph.View.webglLine(3014898687)},u=function(){q.updateTransform(l),r.updateTransform(l)},v=function(){l=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},w=function(){b&&c&&(e=c.width=Math.max(b.offsetWidth,1),f=c.height=Math.max(b.offsetHeight,1),d&&d.viewport(0,0,e,f),q&&q.updateSize(e/2,f/2),r&&r.updateSize(e/2,f/2))},x=function(a){a.fire("rescaled")},y={getLinkUI:function(a){return p[a]},getNodeUI:function(a){return o[a]},node:function(a){return"function"==typeof a?(s=a,this):void 0},link:function(a){return"function"==typeof a?(t=a,this):void 0},placeNode:function(a){return g=a,this},placeLink:function(a){return h=a,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){k>0&&q.render(),j>0&&r.render()},bringLinkToFront:function(a){var b,c,d=q.getFrontLinkId();q.bringToFront(a),d>a.id&&(b=a.id,c=n[d],n[d]=n[b],n[d].id=d,n[b]=c,n[b].id=b)},graphCenterChanged:function(a,b){l[12]=2*a/e-1,l[13]=1-2*b/f,u()},addLink:function(a,b){var c=k++,d=t(a);return d.id=c,d.pos=b,q.createLink(d),n[c]=d,p[a.id]=d,d},addNode:function(a,b){var c=j++,d=s(a);return d.id=c,d.position=b,d.node=a,r.createNode(d),m[c]=d,o[a.id]=d,d},translateRel:function(a,b){l[12]+=2*l[0]*a/e/l[0],l[13]-=2*l[5]*b/f/l[5],u()},scale:function(a,b){var c=2*b.x/e-1,d=1-2*b.y/f;return c-=l[12],d-=l[13],l[12]+=c*(1-a),l[13]+=d*(1-a),l[0]*=a,l[5]*=a,u(),x(this),l[0]},resetScale:function(){return v(),d&&(w(),u()),this},init:function(g){var h={};if(a.preserveDrawingBuffer&&(h.preserveDrawingBuffer=!0),b=g,c=window.document.createElement("canvas"),w(),v(),b.appendChild(c),d=c.getContext("experimental-webgl",h),!d){var j="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(j),j}if(a.enableBlending&&(d.blendFunc(d.SRC_ALPHA,d.ONE_MINUS_SRC_ALPHA),d.enable(d.BLEND)),a.clearColor){var k=a.clearColorValue;d.clearColor(k.r,k.g,k.b,k.a),this.beginRender=function(){d.clear(d.COLOR_BUFFER_BIT)}}q.load(d),q.updateSize(e/2,f/2),r.load(d),r.updateSize(e/2,f/2),u(),"function"==typeof i&&i(c)},release:function(a){c&&a&&a.removeChild(c)},isSupported:function(){var a=window.document.createElement("canvas"),b=a&&a.getContext&&a.getContext("experimental-webgl");return b},releaseLink:function(a){k>0&&(k-=1);var b=p[a.id];delete p[a.id],q.removeLink(b);var c=b.id;if(k>c){if(0===k||k===c)return;var d=n[k];n[c]=d,d.id=c}},releaseNode:function(a){j>0&&(j-=1);var b=o[a.id];delete o[a.id],r.removeNode(b);var c=b.id;if(j>c){if(0===j||j===c)return;var d=m[j];m[c]=d,d.id=c,r.replaceProperties(b,d)}},renderNodes:function(){for(var a={x:0,y:0},b=0;j>b;++b){var c=m[b];a.x=c.position.x,a.y=-c.position.y,g&&g(c,a),r.position(c,a)}},renderLinks:function(){if(!this.omitLinksRendering)for(var a={x:0,y:0},b={x:0,y:0},c=0;k>c;++c){var d=n[c],e=d.pos.from;b.x=e.x,b.y=-e.y,e=d.pos.to,a.x=e.x,a.y=-e.y,h&&h(d,b,a),q.position(d,b,a)}},getGraphicsRoot:function(a){return"function"==typeof a&&(c?a(c):i=a),c},setNodeProgram:function(a){if(!d&&a)r=a;else if(a)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(a){if(!d&&a)q=a;else if(a)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(a){return a.x=2*a.x/e-1,a.y=1-2*a.y/f,a.x=(a.x-l[12])/l[0],a.y=(a.y-l[13])/l[5],a.x*=e/2,a.y*=-f/2,a},getNodeAtClientPos:function(a,b){if("function"!=typeof b)return null;this.transformClientToGraphCoordinates(a);for(var c=0;j>c;++c)if(b(m[c],a.x,a.y))return m[c].node;return null}};return Viva.Graph.Utils.events(y).extend(),y},Viva.Graph.webglInputEvents=function(a){if(a.webglInputEvents)return a.webglInputEvents;var b,c,d=function(a,b,c){if(a&&a.size){var d=a.position,e=a.size;return d.x-eg-s&&f[0]===r?q(m,f):q(l,f),s=g,q(j,f)&&o(a))})};return a.getGraphicsRoot(r),a.webglInputEvents={mouseEnter:function(a){return"function"==typeof a&&g.push(a),this},mouseLeave:function(a){return"function"==typeof a&&h.push(a),this},mouseDown:function(a){return"function"==typeof a&&i.push(a),this},mouseUp:function(a){return"function"==typeof a&&j.push(a),this},mouseMove:function(a){return"function"==typeof a&&k.push(a),this},click:function(a){return"function"==typeof a&&l.push(a),this},dblClick:function(a){return"function"==typeof a&&m.push(a),this},mouseCapture:function(a){f=a},releaseMouseCapture:function(){f=null}},a.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(a,b){var c=Viva.Graph.webglInputEvents(b),d=null,e={},f={x:0,y:0};return c.mouseDown(function(a,b){d=a,f.x=b.clientX,f.y=b.clientY,c.mouseCapture(d);var g=e[a.id];return g&&g.onStart&&g.onStart(b,f),!0}).mouseUp(function(a){c.releaseMouseCapture(d),d=null;var b=e[a.id];return b&&b.onStop&&b.onStop(),!0}).mouseMove(function(a,b){if(d){var c=e[d.id];return c&&c.onDrag&&c.onDrag(b,{x:b.clientX-f.x,y:b.clientY-f.y}),f.x=b.clientX,f.y=b.clientY,!0}}),{bindDragNDrop:function(a,b){e[a.id]=b,b||delete e[a.id]}}}; \ No newline at end of file diff --git a/src/View/webglGraphics.js b/src/View/webglGraphics.js index a8ee4ba..b053197 100644 --- a/src/View/webglGraphics.js +++ b/src/View/webglGraphics.js @@ -36,7 +36,12 @@ Viva.Graph.View.webglGraphics = function (options) { height, nodesCount = 0, linksCount = 0, - transform, + transform = [ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + ], userPlaceNodeCallback, userPlaceLinkCallback, nodes = [], @@ -191,7 +196,9 @@ Viva.Graph.View.webglGraphics = function (options) { * Sets translate operation that should be applied to all nodes and links. */ graphCenterChanged : function (x, y) { - updateSize(); + transform[12] = (2 * x / width) - 1; + transform[13] = 1 - (2 * y / height); + updateTransformUniform(); }, /** From b99db2b2992da5dd017df2b1a96fbd784aa2d665 Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 19 Feb 2014 08:51:09 -0800 Subject: [PATCH 064/276] 0.5.4 Thanks to sgerard@ webgl now supports centering on node via API --- package.json | 2 +- src/version.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index c85cc4f..074b926 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.4.0", + "version": "0.5.1", "description": "Graph Drawing Library", "main": "dist/vivagraph", "directories": { diff --git a/src/version.js b/src/version.js index 5088e05..1f16ae6 100644 --- a/src/version.js +++ b/src/version.js @@ -1 +1 @@ -Viva.Graph.version = '0.5.3'; +Viva.Graph.version = '0.5.4'; From 03ec78a30e874e952e898c5322ca7951b19eae3f Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 19 Feb 2014 08:55:14 -0800 Subject: [PATCH 065/276] Updated readme --- README.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index a9f0e3d..053eb7b 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,11 @@ VivaGraphJS - JavaScript Graph Drawing Library ================================================== **VivaGraphJS** is a free [graph drawing](http://en.wikipedia.org/wiki/Graph_drawing) library for JavaScript. It is designed to be extensible and to support different rendering engines and layout algorithms. At the moment -it supports rendering graphs using WebGL, SVG or CSS formats. Layout algorithms currently implemented are: +it supports rendering graphs using WebGL, SVG or CSS formats. -* [Force Directed](http://en.wikipedia.org/wiki/Force-based_algorithms_\(graph_drawing\)) - based on Barnes-Hut -simulation and optimized for JavaScript language this algorithm gives `N * lg(N) + V` performance per iteration. - -Library provides API which tracks graph changes and reflect changes on the rendering surface -accordingly. +**Note:** Please visit [anvaka/ngraph](https://github.com/anvaka/ngraph) to check +next evolution step of this library. `ngraph` supports rendering graphs to images, +3d graphs rendering, integration with [gephi](https://gephi.org/) and more. Enough talking. Show me the demo! From 5bf3c065bf9d062379f03869eafde5d6dbf01e7d Mon Sep 17 00:00:00 2001 From: Andrei Kashcha Date: Wed, 19 Feb 2014 08:56:26 -0800 Subject: [PATCH 066/276] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 053eb7b..d0d9947 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -VivaGraphJS - JavaScript Graph Drawing Library +Graph Drawing Library ================================================== **VivaGraphJS** is a free [graph drawing](http://en.wikipedia.org/wiki/Graph_drawing) library for JavaScript. It is designed to be extensible and to support different rendering engines and layout algorithms. At the moment From 6fafde8f25e486500f25b96548800e67d2b0e472 Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 19 Feb 2014 08:58:09 -0800 Subject: [PATCH 067/276] 0.5.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 074b926..1467af1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.5.1", + "version": "0.5.4", "description": "Graph Drawing Library", "main": "dist/vivagraph", "directories": { From c4d17ed32bc81027241710e982b873fdcd13fa8a Mon Sep 17 00:00:00 2001 From: Nadav Greenberg Date: Sat, 22 Feb 2014 11:07:30 +0200 Subject: [PATCH 068/276] make the stable threshold a setting so it is configurable per usage --- src/Layout/forceDirected.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Layout/forceDirected.js b/src/Layout/forceDirected.js index 12ee8fb..a52ff2d 100644 --- a/src/Layout/forceDirected.js +++ b/src/Layout/forceDirected.js @@ -4,8 +4,6 @@ Viva.Graph.Layout = Viva.Graph.Layout || {}; Viva.Graph.Layout.forceDirected = function(graph, settings) { - var STABLE_THRESHOLD = 0.001; // Maximum movement of the system which can be considered as stabilized - if (!graph) { throw { message: 'Graph structure cannot be undefined' @@ -76,7 +74,12 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { /** * Default time step (dt) for forces integration */ - timeStep : 20 + timeStep : 20, + + /** + * Maximum movement of the system which can be considered as stabilized + */ + stableThreshold: 0.001 }); var forceSimulator = Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()), @@ -308,7 +311,7 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { var energy = forceSimulator.run(settings.timeStep); updateNodePositions(); - return energy < STABLE_THRESHOLD; + return energy < settings.stableThreshold; }, /* From f18f36a3d89c82c9cc15058fe3cf81dd51168541 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 22 Feb 2014 01:20:32 -0800 Subject: [PATCH 069/276] 0.5.5 --- CHANGELOG | 8 ++++++++ dist/vivagraph.js | 13 ++++++++----- dist/vivagraph.min.js | 4 ++-- package.json | 2 +- src/version.js | 2 +- 5 files changed, 20 insertions(+), 9 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index e902a91..a51d39c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,11 @@ +v0.5.5 + date: Feb 22, 2013 + - Stable threshold can now be configured via options (Tnanks to @grnadav) + +v0.5.4 + date: Feb 19, 2014 + - Webgl renderer supports centering API (Thanks to @sgerard) + v0.5.3 date: Dec 27, 2013 - Small clean up in renderer diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 8b35745..26e0903 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -7,7 +7,7 @@ Viva.Graph = Viva.Graph || {}; if (typeof module !== 'undefined' && module.exports) { module.exports = Viva; } -Viva.Graph.version = '0.5.3'; +Viva.Graph.version = '0.5.4'; /** * Extends target object with given fields/values in the options object. * Unlike jQuery's extend this method does not override target object @@ -2090,8 +2090,6 @@ Viva.Graph.Physics.forceSimulator = function (forceIntegrator) { Viva.Graph.Layout = Viva.Graph.Layout || {}; Viva.Graph.Layout.forceDirected = function(graph, settings) { - var STABLE_THRESHOLD = 0.001; // Maximum movement of the system which can be considered as stabilized - if (!graph) { throw { message: 'Graph structure cannot be undefined' @@ -2162,7 +2160,12 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { /** * Default time step (dt) for forces integration */ - timeStep : 20 + timeStep : 20, + + /** + * Maximum movement of the system which can be considered as stabilized + */ + stableThreshold: 0.001 }); var forceSimulator = Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()), @@ -2394,7 +2397,7 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { var energy = forceSimulator.run(settings.timeStep); updateNodePositions(); - return energy < STABLE_THRESHOLD; + return energy < settings.stableThreshold; }, /* diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 5272cbf..3c0f1f9 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.3",Viva.lazyExtend=function(a,b){var c;if(a||(a={}),b)for(c in b)if(b.hasOwnProperty(c)){var d=a.hasOwnProperty(c),e=typeof b[c],f=!d||typeof a[c]!==e;f?a[c]=b[c]:"object"===e&&(a[c]=Viva.lazyExtend(a[c],b[c]))}return a},Viva.random=function(){var a,b=arguments[0];a="number"==typeof b?b:"string"==typeof b?b.length:+new Date;var c=function(){return a=a+2127912214+(a<<12)&4294967295,a=4294967295&(3345072700^a^a>>>19),a=a+374761393+(a<<5)&4294967295,a=4294967295&(a+3550635116^a<<9),a=a+4251993797+(a<<3)&4294967295,a=4294967295&(3042594569^a^a>>>16),(268435455&a)/268435456};return{next:function(a){return Math.floor(c()*a)},nextDouble:function(){return c()}}},Viva.randomIterator=function(a,b){return b=b||Viva.random(),{forEach:function(c){var d,e,f;for(d=a.length-1;d>0;--d)e=b.next(d+1),f=a[e],a[e]=a[d],a[d]=f,c(f);a.length&&c(a[0])},shuffle:function(){var c,d,e;for(c=a.length-1;c>0;--c)d=b.next(c+1),e=a[d],a[d]=a[c],a[c]=e;return a}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var a=window.navigator.userAgent.toLowerCase(),b=/(webkit)[ \/]([\w.]+)/,c=/(opera)(?:.*version)?[ \/]([\w.]+)/,d=/(msie) ([\w.]+)/,e=/(mozilla)(?:.*? rv:([\w.]+))?/,f=b.exec(a)||c.exec(a)||d.exec(a)||a.indexOf("compatible")<0&&e.exec(a)||[];return{browser:f[1]||"",version:f[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(a,b){if(b.indexOf)return b.indexOf(a);var c,d=b.length;for(c=0;d>c;c+=1)if(b.hasOwnProperty(c)&&b[c]===a)return c;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(a){if(!a)throw{message:"Cannot get dimensions of undefined container"};var b=a.clientWidth,c=a.clientHeight;return{left:0,top:0,width:b,height:c}},Viva.Graph.Utils.findElementPosition=function(a){var b=0,c=0;if(a.offsetParent)do b+=a.offsetLeft,c+=a.offsetTop;while(null!==(a=a.offsetParent));return[b,c]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(a){var b=function(a){var b={};return a.fire=function(a,c){var d,e,f,g;if("string"!=typeof a)throw"Only strings can be used as even type";if(b.hasOwnProperty(a))for(d=b[a],g=0;gc?d=-1:c>o&&(d=1),e(a,d,{x:a.touches[0].clientX,y:a.touches[0].clientY}),o=c,r(a),s(a)}},B=function(a){n=!1,i.stop("touchmove",A),i.stop("touchend",B),i.stop("touchcancel",B),h=null,d&&d(a)},C=function(a,c){r(a),s(a),l=c.clientX,m=c.clientY,h=a.target||a.srcElement,b&&b(a,{x:l,y:m}),n||(n=!0,i.on("touchmove",A),i.on("touchend",B),i.on("touchcancel",B))},D=function(b){return console.log("Touch start for ",a),1===b.touches.length?C(b,b.touches[0]):void(2===b.touches.length&&(r(b),s(b),o=z(b.touches[0],b.touches[1])))};return j.on("mousedown",v),j.on("touchstart",D),{onStart:function(a){return b=a,this},onDrag:function(a){return c=a,this},onStop:function(a){return d=a,this},onScroll:function(a){return y(a),this},release:function(){i.stop("mousemove",u),i.stop("mousedown",v),i.stop("mouseup",w),i.stop("touchmove",A),i.stop("touchend",B),i.stop("touchcancel",B),y(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(a,b){var c={};return{bindDragNDrop:function(a,d){var e;if(d){var f=b.getNodeUI(a.id);e=Viva.Graph.Utils.dragndrop(f),"function"==typeof d.onStart&&e.onStart(d.onStart),"function"==typeof d.onDrag&&e.onDrag(d.onDrag),"function"==typeof d.onStop&&e.onStop(d.onStop),c[a.id]=e}else(e=c[a.id])&&(e.release(),delete c[a.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var a,b,c=0,d=["ms","moz","webkit","o"];for(b="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},a=0;a=0==r>=4?null:(j=h-f,l=e-g,n=g*f-e*h,o=j*a+l*b+n,p=j*c+l*d+n,0!==o&&0!==p&&o>=0==p>=0?null:(s=i*l-j*k,0===s?null:(t=0>s?-s/2:s/2,t=0,u=k*n-l*m,v.x=(0>u?u-t:u+t)/s,u=j*m-i*n,v.y=(0>u?u-t:u+t)/s,v)))},intersectRect:function(a,b,c,d,e,f,g,h){return this.intersect(a,b,a,d,e,f,g,h)||this.intersect(a,d,c,d,e,f,g,h)||this.intersect(c,d,c,b,e,f,g,h)||this.intersect(c,b,a,b,e,f,g,h)},convexHull:function(a){var b=function(a,b){var c,d,e=function(b){var c=b.x-a.x,d=b.y-a.y,e=c>0?1:-1;return e*c*c/(c*c+d*d)},f=b.sort(function(a,b){return e(b)-e(a)}),g=f[0],h=e(g),i=g.x-a.x,j=g.y-a.y,k=i*i+j*j;for(d=1;dc?f.splice(d,1):f.splice(d-1,1)):h=l}return f},c=function(a,b,c){return(c.x-a.x)*(b.y-a.y)-(c.y-a.y)*(b.x-a.x)<0};if(a.length<3)return a;var d,e=0;for(d=0;d0&&(g(a),f.length=0)},j=function(a,b){f.push({node:a,changeType:b})},k=function(a,b){f.push({link:a,changeType:b})},l={addNode:function(b,c){if("undefined"==typeof b)throw{message:"Invalid node identifier"};h();var e=this.getNode(b);return e?j(e,"update"):(e=new Viva.Graph.Node(b),d++,j(e,"add")),e.data=c,a[b]=e,i(this),e},addLink:function(a,d,e){h();var f=this.getNode(a)||this.addNode(a),g=this.getNode(d)||this.addNode(d),j=a.toString()+"👉 "+d.toString(),l=c.hasOwnProperty(j);(l||this.hasLink(a,d))&&(l||(c[j]=0),j+="@"+ ++c[j]);var m=new Viva.Graph.Link(a,d,e,j);return b.push(m),f.links.push(m),g.links.push(m),k(m,"add"),i(this),m},removeLink:function(a){if(!a)return!1;var c=Viva.Graph.Utils.indexOfElementInArray(a,b);if(0>c)return!1;h(),b.splice(c,1);var d=this.getNode(a.fromId),e=this.getNode(a.toId);return d&&(c=Viva.Graph.Utils.indexOfElementInArray(a,d.links),c>=0&&d.links.splice(c,1)),e&&(c=Viva.Graph.Utils.indexOfElementInArray(a,e.links),c>=0&&e.links.splice(c,1)),k(a,"remove"),i(this),!0},removeNode:function(b){var c=this.getNode(b);if(!c)return!1;for(h();c.links.length;){var e=c.links[0];this.removeLink(e)}a[b]=null,delete a[b],d--,j(c,"remove"),i(this)},getNode:function(b){return a[b]},getNodesCount:function(){return d},getLinksCount:function(){return b.length},getLinks:function(a){var b=this.getNode(a);return b?b.links:null},forEachNode:function(b){if("function"==typeof b){var c;for(c in a)if(a.hasOwnProperty(c)&&b(a[c]))return}},forEachLinkedNode:function(b,c,d){var e,f,g,h=this.getNode(b);if(h&&h.links&&"function"==typeof c)if(d)for(e=0;ec;++c)a(b[c])},beginUpdate:function(){h()},endUpdate:function(){i(this)},clear:function(){var a=this;a.beginUpdate(),a.forEachNode(function(b){a.removeNode(b.id)}),a.endUpdate()},hasLink:function(a,b){var c,d=this.getNode(a);if(!d)return null;for(c=0;cc;++c){var h=a.bodies[c],i=b/h.mass;h.velocity.x+=i*h.force.x,h.velocity.y+=i*h.force.y;var j=h.velocity.x,k=h.velocity.y,l=Math.sqrt(j*j+k*k);l>d&&(h.velocity.x=d*j/l,h.velocity.y=d*k/l),e=b*h.velocity.x,f=b*h.velocity.y,h.location.x+=e,h.location.y+=f}return e*e+f*f}}},Viva.Graph.Physics.nbodyForce=function(a){function b(a,b){this.node=a,this.body=b}function c(){this.stack=[],this.popIdx=0}a=Viva.lazyExtend(a||{gravity:-1,theta:.8}),c.prototype={isEmpty:function(){return 0===this.popIdx},push:function(a,c){var d=this.stack[this.popIdx];d?(d.node=a,d.body=c):this.stack[this.popIdx]=new b(a,c),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var d=a.gravity,e=[],f=new c,g=a.theta,h=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),i=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},j=[],k=0,l=function(){var a;return j[k]?(a=j[k],a.quads[0]=null,a.quads[1]=null,a.quads[2]=null,a.quads[3]=null,a.body=null,a.mass=a.massX=a.massY=0,a.left=a.right=a.top=a.bottom=0,a.isInternal=!1):(a=new i,j[k]=a),++k,a},m=l(),n=function(a,b){var c=Math.abs(a.x-b.x),d=Math.abs(a.y-b.y);return 1e-8>c&&1e-8>d},o=function(a){for(f.reset(),f.push(m,a);!f.isEmpty();){var b=f.pop(),c=b.node,d=b.body;if(c.isInternal){var e=d.location.x,g=d.location.y;c.mass=c.mass+d.mass,c.massX=c.massX+d.mass*e,c.massY=c.massY+d.mass*g;var i=0,j=c.left,k=(c.right+j)/2,o=c.top,p=(c.bottom+o)/2;if(e>k){i+=1;var q=j;j=k,k+=k-q}if(g>p){i+=2;var r=o;o=p,p+=p-r}var s=c.quads[i];s||(s=l(),s.left=j,s.top=o,s.right=k,s.bottom=p,c.quads[i]=s),f.push(s,d)}else if(c.body){var t=c.body;if(c.body=null,c.isInternal=!0,n(t.location,d.location)){if(c.right-c.left<1e-8)return;do{var u=h.nextDouble(),v=(c.right-c.left)*u,w=(c.bottom-c.top)*u;t.location.x=c.left+v,t.location.y=c.top+w}while(n(t.location,d.location))}f.push(c,t),f.push(c,d)}else c.body=d}},p=function(a){var b,c,f,i,j=e,k=1,l=0,n=1;for(j[0]=m;k;){var o=j[l],p=o.body;k-=1,l+=1,p&&p!==a?(c=p.location.x-a.location.x,f=p.location.y-a.location.y,i=Math.sqrt(c*c+f*f),0===i&&(c=(h.nextDouble()-.5)/50,f=(h.nextDouble()-.5)/50,i=Math.sqrt(c*c+f*f)),b=d*p.mass*a.mass/(i*i*i),a.force.x=a.force.x+b*c,a.force.y=a.force.y+b*f):(c=o.massX/o.mass-a.location.x,f=o.massY/o.mass-a.location.y,i=Math.sqrt(c*c+f*f),0===i&&(c=(h.nextDouble()-.5)/50,f=(h.nextDouble()-.5)/50,i=Math.sqrt(c*c+f*f)),(o.right-o.left)/ii&&(c=i),i>e&&(e=i),d>j&&(d=j),j>f&&(f=j)}var n=e-c,p=f-d;for(n>p?f=d+n:e=c+p,k=0,m=l(),m.left=c,m.right=e,m.top=d,m.bottom=f,b=h;b--;)o(g[b],m)};return{insert:o,init:q,update:p,options:function(a){return a?("number"==typeof a.gravity&&(d=a.gravity),"number"==typeof a.theta&&(g=a.theta),this):{gravity:d,theta:g}}}},Viva.Graph.Physics.dragForce=function(a){a||(a={});var b={coeff:a.coeff||.01};return{update:function(a){a.force.x-=b.coeff*a.velocity.x,a.force.y-=b.coeff*a.velocity.y},options:function(a){return a?("number"==typeof a.coeff&&(b.coeff=a.coeff),this):b}}},Viva.Graph.Physics.springForce=function(a){a=Viva.lazyExtend(a,{length:50,coeff:22e-5});var b=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(c){var d=c.body1,e=c.body2,f=c.length<0?a.length:c.length,g=e.location.x-d.location.x,h=e.location.y-d.location.y,i=Math.sqrt(g*g+h*h);0===i&&(g=(b.nextDouble()-.5)/50,h=(b.nextDouble()-.5)/50,i=Math.sqrt(g*g+h*h));var j=i-f,k=(!c.coeff||c.coeff<0?a.coeff:c.coeff)*j/i*c.weight;d.force.x+=k*g,d.force.y+=k*h,e.force.x+=-k*g,e.force.y+=-k*h},options:function(b){return b?("number"==typeof b.length&&(a.length=b.length),"number"==typeof b.coeff&&(a.coeff=b.coeff),this):a}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(a){var b,c,d,e=a,f=[],g=[];return{speedLimit:1,bodies:f,accumulate:function(){var a,e;for(c.init(this),a=f.length;a--;)e=f[a],e.force.x=0,e.force.y=0,c.update(e),d.update(e);for(a=g.length;a--;)b.update(g[a])},run:function(a){return this.accumulate(),e.integrate(this,a)},addBody:function(a){if(!a)throw{message:"Cannot add null body to force simulator"};return f.push(a),a},removeBody:function(a){if(!a)return!1;var b=Viva.Graph.Utils.indexOfElementInArray(a,f);return 0>b?!1:f.splice(b,1)},addSpring:function(a,b,c,d,e){if(!a||!b)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof c)throw{message:"Spring length should be a number"};d="number"==typeof d?d:1;var f=new Viva.Graph.Physics.Spring(a,b,c,e>=0?e:-1,d);return g.push(f),f},removeSpring:function(a){if(!a)return!1;var b=Viva.Graph.Utils.indexOfElementInArray(a,g);return 0>b?!1:g.splice(b,1)},setNbodyForce:function(a){if(!a)throw{message:"Cannot add mighty (unknown) force to the simulator"};c=a},setDragForce:function(a){if(!a)throw{message:"Cannot add mighty (unknown) force to the simulator"};d=a},setSpringForce:function(a){if(!a)throw{message:"Cannot add unknown force to the simulator"};b=a}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(a,b){var c=.001;if(!a)throw{message:"Graph structure cannot be undefined"};b=Viva.lazyExtend(b,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02,springTransform:function(){},timeStep:20});var d=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),e=Viva.Graph.Physics.nbodyForce({gravity:b.gravity,theta:b.theta}),f=Viva.Graph.Physics.springForce({length:b.springLength,coeff:b.springCoeff}),g=Viva.Graph.Physics.dragForce({coeff:b.dragCoeff}),h=new Viva.Graph.Rect,i=Viva.random("ted.com",103,114,101,97,116),j={},k=function(a){if(a.position)return a.position;var c=(h.x1+h.x2)/2,d=(h.y1+h.y2)/2,e=b.springLength;if(a.links&&a.links.length>0){var f=a.links[0],g=f.fromId!==a.id?j[f.fromId]:j[f.toId];g&&g.location&&(c=g.location.x,d=g.location.y)}return{x:c+i.next(e)-e/2,y:d+i.next(e)-e/2}},l=function(a){return j[a]},m=function(a){j[a]=null,delete j[a]},n={},o=function(b){var c=l(b);c.mass=1+a.getLinks(b).length/3},p=function(a){return a&&(a.isPinned||a.data&&a.data.isPinned)},q=function(a){return a.isPinned},r=function(b){var c=l(b);if(!c){var e=a.getNode(b);if(!e)return;c=new Viva.Graph.Physics.Body,j[b]=c;var f=k(e);c.loc(f),o(b),p(e)&&(c.isPinned=!0),d.addBody(c)}},s=function(a){r(a.id)},t=function(b){var c=l(b.id);c&&(m(b.id),d.removeBody(c),0===a.getNodesCount()&&(h.x1=h.y1=0,h.x2=h.y2=0))},u=function(a){o(a.fromId),o(a.toId);var c=l(a.fromId),e=l(a.toId),f=d.addSpring(c,e,-1,a.weight);b.springTransform(a,f),n[a.id]=f},v=function(b){var c=n[b.id];if(c){var e=a.getNode(b.fromId),f=a.getNode(b.toId);e&&o(e.id),f&&o(f.id),delete n[b.id],d.removeSpring(c)}},w=function(a){for(var b=0;bd&&(d=g.location.x),g.location.ye&&(e=g.location.y)}h.x1=b,h.x2=d,h.y1=c,h.y2=e}};return d.setSpringForce(f),d.setNbodyForce(e),d.setDragForce(g),x(),{run:function(a){var b;for(a=a||50,b=0;a>b;++b)this.step()},step:function(){var a=d.run(b.timeStep);return y(),c>a},isNodePinned:function(a){var b=l(a.id);return b?q(b):void 0},pinNode:function(a,b){var c=l(a.id);c.isPinned=!!b},getNodePosition:function(a){var b=l(a);return b||(r(a),b=l(a)),b&&b.location},getLinkPosition:function(a){var b=this.getNodePosition(a.fromId),c=this.getNodePosition(a.toId);return{from:b,to:c}},setNodePosition:function(a,b,c){var d=l(a.id);d&&(d.prevLocation.x=d.location.x=b,d.prevLocation.y=d.location.y=c)},getGraphRect:function(){return h},dispose:function(){a.removeEventListener("change",w)},springLength:function(a){return 1===arguments.length?(f.options({length:a}),this):f.options().length},springCoeff:function(a){return 1===arguments.length?(f.options({coeff:a}),this):f.options().coeff},gravity:function(a){return 1===arguments.length?(e.options({gravity:a}),this):e.options().gravity},theta:function(a){return 1===arguments.length?(e.options({theta:a}),this):e.options().theta},drag:function(a){return 1===arguments.length?(g.options({coeff:a}),this):g.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(a,b){b=Viva.lazyExtend(b,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var c=Viva.random(b.seed),d=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),e=function(){return new Viva.Graph.Point2d(c.next(b.maxX),c.next(b.maxY))},f=function(a,b){a.xb.x2&&(b.x2=a.x),a.yb.y2&&(b.y2=a.y)},g={},h=function(a){a&&(g[a.id]||(g[a.id]=e(a)),f(g[a.id],d))},i=function(){0!==a.getNodesCount()&&(d.x1=Number.MAX_VALUE,d.y1=Number.MAX_VALUE,d.x2=Number.MIN_VALUE,d.y2=Number.MIN_VALUE,a.forEachNode(h))},j=function(a){for(var b=0;b0)for(a=0;ab,c)}),a.forEachNode(F),O(),f=Viva.Graph.Utils.events(a),f.on("changed",L)},R=function(){k=!1,O(),N(),t.stop("resize",M),u.removeAllListeners(),e.stop(),a.forEachLink(function(a){b.renderLinks&&E(a)}),a.forEachNode(function(a){G(a),C(a)}),h.dispose(),I()};return{run:function(a){return k||(s(),z(),A(),H(),Q(),k=!0),x(a),this},reset:function(){i.resetScale(),A(),r.scale=1},pause:function(){e.stop()},resume:function(){e.restart()},rerender:function(){return v(),this},zoomOut:function(){P(!0)},zoomIn:function(){P(!1)},moveTo:function(a,b){i.graphCenterChanged(r.offsetX-a*r.scale,r.offsetY-b*r.scale),v()},getGraphics:function(){return i},dispose:function(){R()},on:function(a,b){return u.addEventListener(a,b),this},off:function(a,b){return u.removeEventListener(a,b),this}}},Viva.Graph.serializer=function(){var a=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},b=function(a){return{id:a.id,data:a.data}},c=function(a){return{fromId:a.fromId,toId:a.toId,data:a.data}},d=function(a){return a},e=function(a){return a};return{storeToJSON:function(d,e,f){if(!d)throw"Graph is not defined";a(),e=e||b,f=f||c;var g={nodes:[],links:[]};return d.forEachNode(function(a){g.nodes.push(e(a))}),d.forEachLink(function(a){g.links.push(f(a))}),JSON.stringify(g)},loadFromJSON:function(b,c,f){if("string"!=typeof b)throw"String expected in loadFromJSON() method";a(),c=c||d,f=f||e;var g,h=JSON.parse(b),i=Viva.Graph.graph();if(!h||!h.nodes||!h.links)throw"Passed json string does not represent valid graph";for(g=0;gc?void d.push({name:a,probability:e/b}):!0}),d},g=function(a){var b=[];return a.forEachNode(function(a){var c=Viva.Graph._community.occuranceMap(d);c.add(a.id),a.slpa={memory:c},b.push(a.id)}),b},h=function(a,c){var f,g=Viva.randomIterator(c,e),h=function(b){var c=a.getNode(b),e=Viva.Graph._community.occuranceMap(d);a.forEachLinkedNode(b,function(a){var b=a.slpa.memory.getRandomWord();e.add(b)});var f=e.getMostPopularFair();c.slpa.memory.add(f)};for(f=0;b-1>f;++f)g.forEach(h)},i=function(a){var d={};return a.forEachNode(function(a){var e,g=f(a.slpa.memory,c*b);for(e=0;ea?-1:a>c?1:0})},g=function(){d&&(f(),d=!1)};return{add:function(a){a=String(a),b.hasOwnProperty(a)?b[a]+=1:b[a]=1,c.push(a),d=!0},getWordCount:function(a){return b[a]||0},getMostPopularFair:function(){if(1===c.length)return c[0];g();var d,f=0;for(d=1;da)throw{message:"At least two nodes expected for complete graph"};var b,c,d=Viva.Graph.graph();for(d.Name="Complete K"+a,b=0;a>b;++b)for(c=b+1;a>c;++c)b!==c&&d.addLink(b,c);return d},completeBipartite:function(a,b){if(!a||!b||0>a||0>b)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var c,d,e=Viva.Graph.graph();for(e.Name="Complete K "+a+","+b,c=0;a>c;++c)for(d=a;a+b>d;++d)e.addLink(c,d);return e},ladder:function(a){if(!a||0>a)throw{message:"Invalid number of nodes"};var b,c=Viva.Graph.graph();for(c.Name="Ladder graph "+a,b=0;a-1>b;++b)c.addLink(b,b+1),c.addLink(a+b,a+b+1),c.addLink(b,a+b);return c.addLink(a-1,2*a-1),c},circularLadder:function(a){if(!a||0>a)throw{message:"Invalid number of nodes"};var b=this.ladder(a);return b.Name="Circular ladder graph "+a,b.addLink(0,a-1),b.addLink(a,2*a-1),b},grid:function(a,b){var c,d,e=Viva.Graph.graph(); -for(e.Name="Grid graph "+a+"x"+b,c=0;a>c;++c)for(d=0;b>d;++d){var f=c+d*a;c>0&&e.addLink(f,c-1+d*a),d>0&&e.addLink(f,c+(d-1)*a)}return e},path:function(a){if(!a||0>a)throw{message:"Invalid number of nodes"};var b,c=Viva.Graph.graph();for(c.Name="Path graph "+a,c.addNode(0),b=1;a>b;++b)c.addLink(b-1,b);return c},lollipop:function(a,b){if(!b||0>b||!a||0>a)throw{message:"Invalid number of nodes"};var c,d=this.complete(a);for(d.Name="Lollipop graph. Head x Path "+a+"x"+b,c=0;b>c;++c)d.addLink(a+c-1,a+c);return d},balancedBinTree:function(a){var b,c=Viva.Graph.graph(),d=Math.pow(2,a);for(c.Name="Balanced bin tree graph "+a,b=1;d>b;++b){var e=b,f=2*e,g=2*e+1;c.addLink(e,f),c.addLink(e,g)}return c},randomNoLinks:function(a){if(!a||0>a)throw{message:"Invalid number of nodes"};var b,c=Viva.Graph.graph();for(c.Name="Random graph, no Links: "+a,b=0;a>b;++b)c.addNode(b);return c}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var a,b,c,d="OLD_IE",e=1,f=1,g=function(){var a,b,c=Viva.BrowserInfo.browser;switch(c){case"mozilla":a="Moz";break;case"webkit":a="webkit";break;case"opera":a="O";break;case"msie":if(b=Viva.BrowserInfo.version.split(".")[0],!(b>8))return d;a="ms"}return a?a+"Transform":null}(),h=function(){return g===d?function(a,b,c,d){var e=Math.cos(d),f=Math.sin(d);0>d&&(d=2*Math.PI+d),d=n.byteLength){var a=new ArrayBuffer(2*n.byteLength),b=new Float32Array(a),c=new Uint32Array(a);c.set(p),o=b,p=c,n=a}};return{load:function(f){b=f,e=Viva.Graph.webgl(f),a=e.createProgram(m,l),b.useProgram(a),d=e.getLocations(a,["a_vertexPos","a_color","u_screenSize","u_transform"]),b.enableVertexAttribArray(d.vertexPos),b.enableVertexAttribArray(d.color),c=b.createBuffer()},position:function(a,b){var c=a.id;o[c*j]=b.x,o[c*j+1]=b.y,o[c*j+2]=a.size,p[c*j+3]=a.color},updateTransform:function(a){i=!0,h=a},updateSize:function(a,b){f=a,g=b,i=!0},removeNode:function(a){q>0&&(q-=1),a.id0&&e.copyArrayPart(p,a.id*j,q*j,j)},createNode:function(){r(),q+=1},replaceProperties:function(){},render:function(){b.useProgram(a),b.bindBuffer(b.ARRAY_BUFFER,c),b.bufferData(b.ARRAY_BUFFER,n,b.DYNAMIC_DRAW),i&&(i=!1,b.uniformMatrix4fv(d.transform,!1,h),b.uniform2f(d.screenSize,f,g)),b.vertexAttribPointer(d.vertexPos,3,b.FLOAT,!1,j*Float32Array.BYTES_PER_ELEMENT,0),b.vertexAttribPointer(d.color,4,b.UNSIGNED_BYTE,!0,j*Float32Array.BYTES_PER_ELEMENT,12),b.drawArrays(b.POINTS,0,q)}}},Viva.Graph.View.webglLinkProgram=function(){var a,b,c,d,e,f,g,h,i,j,k=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),m=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),n=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),o=0,p=new ArrayBuffer(16*l),q=new Float32Array(p),r=new Uint32Array(p),s=function(){if((o+1)*l>p.byteLength){var a=new ArrayBuffer(2*p.byteLength),b=new Float32Array(a),c=new Uint32Array(a);c.set(r),q=b,r=c,p=a}};return{load:function(f){b=f,d=Viva.Graph.webgl(f),a=d.createProgram(n,m),b.useProgram(a),e=d.getLocations(a,["a_vertexPos","a_color","u_screenSize","u_transform"]),b.enableVertexAttribArray(e.vertexPos),b.enableVertexAttribArray(e.color),c=b.createBuffer()},position:function(a,b,c){var d=a.id,e=d*k;q[e]=b.x,q[e+1]=b.y,r[e+2]=a.color,q[e+3]=c.x,q[e+4]=c.y,r[e+5]=a.color},createLink:function(a){s(),o+=1,f=a.id},removeLink:function(a){o>0&&(o-=1),a.id0&&d.copyArrayPart(r,a.id*k,o*k,k)},updateTransform:function(a){j=!0,i=a},updateSize:function(a,b){g=a,h=b,j=!0},render:function(){b.useProgram(a),b.bindBuffer(b.ARRAY_BUFFER,c),b.bufferData(b.ARRAY_BUFFER,p,b.DYNAMIC_DRAW),j&&(j=!1,b.uniformMatrix4fv(e.transform,!1,i),b.uniform2f(e.screenSize,g,h)),b.vertexAttribPointer(e.vertexPos,2,b.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),b.vertexAttribPointer(e.color,4,b.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),b.drawArrays(b.LINES,0,2*o),f=o-1},bringToFront:function(a){f>a.id&&d.swapArrayPart(q,a.id*k,f*k,k),f>0&&(f-=1)},getFrontLinkId:function(){return f}}},Viva.Graph.View.Texture=function(a){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=a},Viva.Graph.View.webglAtlas=function(a){var b,c,d=Math.sqrt(a||1024)<<0,e=d,f=1,g={},h=0,i=[],j=[],k=function(a){return 0===(a&a-1)},l=function(){var a=new Viva.Graph.View.Texture(d*e);i.push(a)},m=function(b){var c=b/a<<0,e=b%a,f=e/d<<0,g=e%d;return{textureNumber:c,row:f,col:g}},n=function(){c.isDirty=!0,h=0,b=null},o=function(){b&&(window.clearTimeout(b),h+=1,b=null),h>10?n():b=window.setTimeout(n,400)},p=function(a,b){var c=i[a.textureNumber].canvas,d=i[b.textureNumber].ctx,f=b.col*e,g=b.row*e;d.drawImage(c,a.col*e,a.row*e,e,e,f,g,e,e),i[a.textureNumber].isDirty=!0,i[b.textureNumber].isDirty=!0},q=function(a,b,c){var d=m(a),f={offset:a};d.textureNumber>=i.length&&l();var h=i[d.textureNumber];h.ctx.drawImage(b,d.col*e,d.row*e,e,e),j[a]=b.src,g[b.src]=f,h.isDirty=!0,c(f)};if(!k(a))throw"Tiles per texture should be power of two.";return c={isDirty:!1,clearDirty:function(){var a;for(this.isDirty=!1,a=0;a0&&(o-=1),b.id0&&(b.src&&a.remove(b.src),e.copyArrayPart(p,b.id*k,o*k,k))},replaceProperties:function(a,b){b._offset=a._offset},updateTransform:function(a){j=!0,i=a},updateSize:function(a,b){g=a,h=b,j=!0},render:function(){c.useProgram(b),c.bindBuffer(c.ARRAY_BUFFER,d),c.bufferData(c.ARRAY_BUFFER,p,c.DYNAMIC_DRAW),j&&(j=!1,c.uniformMatrix4fv(f.transform,!1,i),c.uniform2f(f.screenSize,g,h)),c.vertexAttribPointer(f.vertexPos,2,c.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),c.vertexAttribPointer(f.customAttributes,1,c.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),r(),c.drawArrays(c.TRIANGLES,0,6*o)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(a){a=Viva.lazyExtend(a,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var b,c,d,e,f,g,h,i,j=0,k=0,l=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],m=[],n=[],o={},p={},q=Viva.Graph.View.webglLinkProgram(),r=Viva.Graph.View.webglNodeProgram(),s=function(){return Viva.Graph.View.webglSquare()},t=function(){return Viva.Graph.View.webglLine(3014898687)},u=function(){q.updateTransform(l),r.updateTransform(l)},v=function(){l=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},w=function(){b&&c&&(e=c.width=Math.max(b.offsetWidth,1),f=c.height=Math.max(b.offsetHeight,1),d&&d.viewport(0,0,e,f),q&&q.updateSize(e/2,f/2),r&&r.updateSize(e/2,f/2))},x=function(a){a.fire("rescaled")},y={getLinkUI:function(a){return p[a]},getNodeUI:function(a){return o[a]},node:function(a){return"function"==typeof a?(s=a,this):void 0},link:function(a){return"function"==typeof a?(t=a,this):void 0},placeNode:function(a){return g=a,this},placeLink:function(a){return h=a,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){k>0&&q.render(),j>0&&r.render()},bringLinkToFront:function(a){var b,c,d=q.getFrontLinkId();q.bringToFront(a),d>a.id&&(b=a.id,c=n[d],n[d]=n[b],n[d].id=d,n[b]=c,n[b].id=b)},graphCenterChanged:function(a,b){l[12]=2*a/e-1,l[13]=1-2*b/f,u()},addLink:function(a,b){var c=k++,d=t(a);return d.id=c,d.pos=b,q.createLink(d),n[c]=d,p[a.id]=d,d},addNode:function(a,b){var c=j++,d=s(a);return d.id=c,d.position=b,d.node=a,r.createNode(d),m[c]=d,o[a.id]=d,d},translateRel:function(a,b){l[12]+=2*l[0]*a/e/l[0],l[13]-=2*l[5]*b/f/l[5],u()},scale:function(a,b){var c=2*b.x/e-1,d=1-2*b.y/f;return c-=l[12],d-=l[13],l[12]+=c*(1-a),l[13]+=d*(1-a),l[0]*=a,l[5]*=a,u(),x(this),l[0]},resetScale:function(){return v(),d&&(w(),u()),this},init:function(g){var h={};if(a.preserveDrawingBuffer&&(h.preserveDrawingBuffer=!0),b=g,c=window.document.createElement("canvas"),w(),v(),b.appendChild(c),d=c.getContext("experimental-webgl",h),!d){var j="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(j),j}if(a.enableBlending&&(d.blendFunc(d.SRC_ALPHA,d.ONE_MINUS_SRC_ALPHA),d.enable(d.BLEND)),a.clearColor){var k=a.clearColorValue;d.clearColor(k.r,k.g,k.b,k.a),this.beginRender=function(){d.clear(d.COLOR_BUFFER_BIT)}}q.load(d),q.updateSize(e/2,f/2),r.load(d),r.updateSize(e/2,f/2),u(),"function"==typeof i&&i(c)},release:function(a){c&&a&&a.removeChild(c)},isSupported:function(){var a=window.document.createElement("canvas"),b=a&&a.getContext&&a.getContext("experimental-webgl");return b},releaseLink:function(a){k>0&&(k-=1);var b=p[a.id];delete p[a.id],q.removeLink(b);var c=b.id;if(k>c){if(0===k||k===c)return;var d=n[k];n[c]=d,d.id=c}},releaseNode:function(a){j>0&&(j-=1);var b=o[a.id];delete o[a.id],r.removeNode(b);var c=b.id;if(j>c){if(0===j||j===c)return;var d=m[j];m[c]=d,d.id=c,r.replaceProperties(b,d)}},renderNodes:function(){for(var a={x:0,y:0},b=0;j>b;++b){var c=m[b];a.x=c.position.x,a.y=-c.position.y,g&&g(c,a),r.position(c,a)}},renderLinks:function(){if(!this.omitLinksRendering)for(var a={x:0,y:0},b={x:0,y:0},c=0;k>c;++c){var d=n[c],e=d.pos.from;b.x=e.x,b.y=-e.y,e=d.pos.to,a.x=e.x,a.y=-e.y,h&&h(d,b,a),q.position(d,b,a)}},getGraphicsRoot:function(a){return"function"==typeof a&&(c?a(c):i=a),c},setNodeProgram:function(a){if(!d&&a)r=a;else if(a)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(a){if(!d&&a)q=a;else if(a)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(a){return a.x=2*a.x/e-1,a.y=1-2*a.y/f,a.x=(a.x-l[12])/l[0],a.y=(a.y-l[13])/l[5],a.x*=e/2,a.y*=-f/2,a},getNodeAtClientPos:function(a,b){if("function"!=typeof b)return null;this.transformClientToGraphCoordinates(a);for(var c=0;j>c;++c)if(b(m[c],a.x,a.y))return m[c].node;return null}};return Viva.Graph.Utils.events(y).extend(),y},Viva.Graph.webglInputEvents=function(a){if(a.webglInputEvents)return a.webglInputEvents;var b,c,d=function(a,b,c){if(a&&a.size){var d=a.position,e=a.size;return d.x-eg-s&&f[0]===r?q(m,f):q(l,f),s=g,q(j,f)&&o(a))})};return a.getGraphicsRoot(r),a.webglInputEvents={mouseEnter:function(a){return"function"==typeof a&&g.push(a),this},mouseLeave:function(a){return"function"==typeof a&&h.push(a),this},mouseDown:function(a){return"function"==typeof a&&i.push(a),this},mouseUp:function(a){return"function"==typeof a&&j.push(a),this},mouseMove:function(a){return"function"==typeof a&&k.push(a),this},click:function(a){return"function"==typeof a&&l.push(a),this},dblClick:function(a){return"function"==typeof a&&m.push(a),this},mouseCapture:function(a){f=a},releaseMouseCapture:function(){f=null}},a.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(a,b){var c=Viva.Graph.webglInputEvents(b),d=null,e={},f={x:0,y:0};return c.mouseDown(function(a,b){d=a,f.x=b.clientX,f.y=b.clientY,c.mouseCapture(d);var g=e[a.id];return g&&g.onStart&&g.onStart(b,f),!0}).mouseUp(function(a){c.releaseMouseCapture(d),d=null;var b=e[a.id];return b&&b.onStop&&b.onStop(),!0}).mouseMove(function(a,b){if(d){var c=e[d.id];return c&&c.onDrag&&c.onDrag(b,{x:b.clientX-f.x,y:b.clientY-f.y}),f.x=b.clientX,f.y=b.clientY,!0}}),{bindDragNDrop:function(a,b){e[a.id]=b,b||delete e[a.id]}}}; \ No newline at end of file +var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.4",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},P=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},N=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",P,!1):e.addEventListener("DOMMouseScroll",P,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",P,!1):e.removeEventListener("DOMMouseScroll",P,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),N(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,d=Math.sqrt(f*f+c*c);d>r&&(u.velocity.x=r*f/d,u.velocity.y=r*c/d),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};r="number"==typeof r?r:1;var o=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,r);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02,springTransform:function(){},timeStep:20,stableThreshold:.001});var n=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),r=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),i=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),o=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),a=new Viva.Graph.Rect,u=Viva.random("ted.com",103,114,101,97,116),s={},f=function(e){if(e.position)return e.position;var n=(a.x1+a.x2)/2,r=(a.y1+a.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],f=o.fromId!==e.id?s[o.fromId]:s[o.toId];f&&f.location&&(n=f.location.x,r=f.location.y)}return{x:n+u.next(i)-i/2,y:r+u.next(i)-i/2}},c=function(e){return s[e]},d=function(e){s[e]=null,delete s[e]},l={},h=function(t){var n=c(t);n.mass=1+e.getLinks(t).length/3},v=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},p=function(e){return e.isPinned},m=function(t){var r=c(t);if(!r){var i=e.getNode(t);if(!i)return;r=new Viva.Graph.Physics.Body,s[t]=r;var o=f(i);r.loc(o),h(t),v(i)&&(r.isPinned=!0),n.addBody(r)}},g=function(e){m(e.id)},y=function(t){var r=c(t.id);r&&(d(t.id),n.removeBody(r),0===e.getNodesCount()&&(a.x1=a.y1=0,a.x2=a.y2=0))},x=function(e){h(e.fromId),h(e.toId);var r=c(e.fromId),i=c(e.toId),o=n.addSpring(r,i,-1,e.weight);t.springTransform(e,o),l[e.id]=o},w=function(t){var r=l[t.id];if(r){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&h(i.id),o&&h(o.id),delete l[t.id],n.removeSpring(r)}},V=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&m(n.node.id),n.link&&x(n.link)):"remove"===n.changeType&&(n.node&&y(n.node),n.link&&w(n.link))}},b=function(){e.forEachNode(g),e.forEachLink(x),e.addEventListener("changed",V)},P=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in s)if(s.hasOwnProperty(o)){var u=s[o];p(u)?(u.location.x=u.prevLocation.x,u.location.y=u.prevLocation.y):(u.prevLocation.x=u.location.x,u.prevLocation.y=u.location.y),t>u.location.x&&(t=u.location.x),u.location.x>r&&(r=u.location.x),n>u.location.y&&(n=u.location.y),u.location.y>i&&(i=u.location.y)}a.x1=t,a.x2=r,a.y1=n,a.y2=i}};return n.setSpringForce(i),n.setNbodyForce(r),n.setDragForce(o),b(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=n.run(t.timeStep);return P(),t.stableThreshold>e},isNodePinned:function(e){var t=c(e.id);return t?p(t):void 0},pinNode:function(e,t){var n=c(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=c(e);return t||(m(e),t=c(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=c(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return a},dispose:function(){e.removeEventListener("change",V)},springLength:function(e){return 1===arguments.length?(i.options({length:e}),this):i.options().length},springCoeff:function(e){return 1===arguments.length?(i.options({coeff:e}),this):i.options().coeff},gravity:function(e){return 1===arguments.length?(r.options({gravity:e}),this):r.options().gravity},theta:function(e){return 1===arguments.length?(r.options({theta:e}),this):r.options().theta},drag:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a={},u=function(e){e&&(a[e.id]||(a[e.id]=i(e)),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&u(n.node)}};return{run:function(){this.step()},step:function(){return s(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,d=!0,l=0,h=0,v=!1,p=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return v=u.step()&&!p,V(),!v},P=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(l=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},N=function(){v=!1,i.restart()},E=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX,g.offsetY),d=!1},L=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),p=!0,N()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),p=!0,V()},onStop:function(){u.pinNode(e,t),p=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),d&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(d=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},D=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);N()},R=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",D),o=null)},z=function(e,t){if(!t){var n=Viva.Graph.Utils.getDimension(f);t={x:n.width/2,y:n.height/2}}var r=Math.pow(1.4,e?-.2:.2);g.scale=s.scale(r,t),V(),w.fire("scale",g.scale)},B=function(){x.on("resize",R),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){z(0>t,n)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",D)},Y=function(){c=!1,O(),F(),x.stop("resize",R),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),E(),G(),C(),B(),c=!0),P(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},zoomOut:function(){z(!0)},zoomIn:function(){z(!1)},moveTo:function(e,t){s.graphCenterChanged(g.offsetX-e*g.scale,g.offsetY-t*g.scale),V()},getGraphics:function(){return s},dispose:function(){Y()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph(); +for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},d=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},l=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?d(e):(d=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,l()},translateRel:function(e,r){t+=e,n+=r,l()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,l()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),d=f.attr("id"),l=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&d===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&l===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i,o=1,a={},u={},s=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},f=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},c=function(){return Viva.Graph.svg("line").attr("stroke","#999")},d=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},l=function(e){e.fire("rescaled")},h={x:0,y:0},v={x:0,y:0},p={x:0,y:0},m=function(){if(e){var t="matrix("+o+", 0, 0,"+o+","+n+","+r+")";e.attr("transform",t)}},g={getNodeUI:function(e){return a[e]},getLinkUI:function(e){return u[e]},node:function(e){return"function"==typeof e?(s=e,this):void 0},link:function(e){return"function"==typeof e?(c=e,this):void 0},placeNode:function(e){return f=e,this},placeLink:function(e){return d=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,m()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(i,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(i).translate(-u.x,-u.y),f=e.getCTM().multiply(s);o=f.a,n=f.e,r=f.f;var c="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",c),l(this),o},resetScale:function(){o=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),l(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),m(),"function"==typeof i&&i(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(t,n){var r=c(t);if(r)return r.position=n,r.link=t,u[t.id]=r,e.childElementCount>0?e.insertBefore(r,e.firstChild):e.appendChild(r),r},releaseLink:function(t){var n=u[t.id];n&&(e.removeChild(n),delete u[t.id])},addNode:function(t,n){var r=s(t);if(r)return r.position=n,r.node=t,a[t.id]=r,e.appendChild(r),r},releaseNode:function(t){var n=a[t.id];n&&(e.removeChild(n),delete a[t.id])},renderNodes:function(){for(var e in a)if(a.hasOwnProperty(e)){var t=a[e];h.x=t.position.x,h.y=t.position.y,f(t,h,t.node)}},renderLinks:function(){for(var e in u)if(u.hasOwnProperty(e)){var t=u[e];v.x=t.position.from.x,v.y=t.position.from.y,p.x=t.position.to.x,p.y=t.position.to.y,d(t,v,p,t.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):i=e),t},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(g).extend(),g},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,d=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(d.x)+" "+Math.round(d.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),l=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),v=new Float32Array(h),p=new Uint32Array(h),m=0,g=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(p),v=t,p=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(l,d),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;v[n*f]=t.x,v[n*f+1]=t.y,v[n*f+2]=e.size,p[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(p,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,d=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),v=0,p=new ArrayBuffer(16*d),m=new Float32Array(p),g=new Uint32Array(p),y=function(){if((v+1)*d>p.byteLength){var e=new ArrayBuffer(2*p.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,p=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,l),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),v+=1,o=e.id},removeLink:function(e){v>0&&(v-=1),v>e.id&&v>0&&r.copyArrayPart(g,e.id*c,v*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,p,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*v),o=v-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},d=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},l=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},v=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},p=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=l(e),o={offset:e};r.textureNumber>=s.length&&d();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=l(t.offset),r=l(o);p(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],v(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){v(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,d=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),l=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,v=0,p=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(l,d),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;p[n]=t.x-e.size,p[n+1]=t.y-e.size,p[n+2]=4*e._offset,p[n+3]=t.x+e.size,p[n+4]=t.y-e.size,p[n+5]=4*e._offset+1,p[n+6]=t.x-e.size,p[n+7]=t.y+e.size,p[n+8]=4*e._offset+2,p[n+9]=t.x-e.size,p[n+10]=t.y+e.size,p[n+11]=4*e._offset+2,p[n+12]=t.x+e.size,p[n+13]=t.y-e.size,p[n+14]=4*e._offset+1,p[n+15]=t.x+e.size,p[n+16]=t.y+e.size,p[n+17]=4*e._offset+3},createNode:function(t){p=i.extendArray(p,v,c),v+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){v>0&&(v-=1),v>t.id&&v>0&&(t.src&&e.remove(t.src),i.copyArrayPart(p,t.id*c,v*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,p,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*v)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f=0,c=0,d=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],l=[],h=[],v={},p={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(d),g.updateTransform(d)},V=function(){d=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},P=function(e){e.fire("rescaled")},N={getLinkUI:function(e){return p[e]},getNodeUI:function(e){return v[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return a=e,this},placeLink:function(e){return u=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){c>0&&m.render(),f>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(e,t){d[12]=2*e/i-1,d[13]=1-2*t/o,w()},addLink:function(e,t){var n=c++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,p[e.id]=r,r},addNode:function(e,t){var n=f++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),l[n]=r,v[e.id]=r,r},translateRel:function(e,t){d[12]+=2*d[0]*e/i/d[0],d[13]-=2*d[5]*t/o/d[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=d[12],r-=d[13],d[12]+=n*(1-e),d[13]+=r*(1-e),d[0]*=e,d[5]*=e,w(),P(this),d[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var f="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(f),f}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof s&&s(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){c>0&&(c-=1);var t=p[e.id];delete p[e.id],m.removeLink(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=h[c];h[n]=r,r.id=n}},releaseNode:function(e){f>0&&(f-=1);var t=v[e.id];delete v[e.id],g.removeNode(t);var n=t.id;if(f>n){if(0===f||f===n)return;var r=l[f];l[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;f>t;++t){var n=l[t];e.x=n.position.x,e.y=-n.position.y,a&&a(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;c>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,u&&u(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):s=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-d[12])/d[0],e.y=(e.y-d[13])/d[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;f>n;++n)if(t(l[n],e.x,e.y))return l[n].node;return null}};return Viva.Graph.Utils.events(N).extend(),N},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},i=function(t){return e.getNodeAtClientPos(t,r)},o=null,a=[],u=[],s=[],f=[],c=[],d=[],l=[],h=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},p=function(e){return v(e),!1},m=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(e){var r={x:0,y:0},g=null,y=+new Date,x=function(e){m(c,[g,e]),r.x=e.clientX,r.y=e.clientY},w=function(){h.stop("mousemove",x),h.stop("mouseup",w)},V=function(){n=e.getBoundingClientRect()};window.addEventListener("resize",V),V(),e.addEventListener("mousemove",function(e){if(!o){var t,s=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,t=i(r),t&&g!==t?(g=t,s=s||m(a,[g])):null===t&&g!==t&&(s=s||m(u,[g]),g=null),s&&v(e)}}),e.addEventListener("mousedown",function(e){var o,a=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]?(a=m(s,o),h.on("mousemove",x),h.on("mouseup",w),t=window.document.onselectstart,window.document.onselectstart=p,g=o[0]):g=null,a&&v(e)}),e.addEventListener("mouseup",function(e){var o,a=+new Date;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]&&(window.document.onselectstart=t,400>a-y&&o[0]===g?m(l,o):m(d,o),y=a,m(f,o)&&v(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&l.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file diff --git a/package.json b/package.json index 1467af1..fda95d0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.5.4", + "version": "0.5.5", "description": "Graph Drawing Library", "main": "dist/vivagraph", "directories": { diff --git a/src/version.js b/src/version.js index 1f16ae6..950cac7 100644 --- a/src/version.js +++ b/src/version.js @@ -1 +1 @@ -Viva.Graph.version = '0.5.4'; +Viva.Graph.version = '0.5.5'; From a49231483487ff8f3f29ce5bd777a1ebe3335293 Mon Sep 17 00:00:00 2001 From: Balamurugan Soundararaj Date: Mon, 24 Feb 2014 17:36:09 +0000 Subject: [PATCH 070/276] Fixed for existing clients and commented in jsdoc format --- src/Core/operations.js | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/src/Core/operations.js b/src/Core/operations.js index 9166802..6263883 100644 --- a/src/Core/operations.js +++ b/src/Core/operations.js @@ -13,27 +13,19 @@ Viva.Graph.operations = function () { * Density 0 - graph has no edges. Runtime: O(1) * * @param graph represents oriented graph structure. + * @param directed (optional boolean) represents if the graph should be treated as a directed graph. * - * @returns density of the graph if graph has nodes. NaN otherwise + * @returns density of the graph if graph has nodes. NaN otherwise. Returns density for undirected graph by default but returns density for directed graph if a boolean 'true' is passed along with the graph. */ - - /* - * Extended the function to give density for a directed graph (since the library usually creates directed graphs) - * If specifically needed the a true value can be passed to the function which will return the value for - * a undirected graph. - * - * I am planning to implement a direced - undirected character to the graphs and expand this operations sections. - * --Bala. - */ - density : function (graph,undirected) { + density : function (graph,directed) { var nodes = graph.getNodesCount(); if (nodes === 0) { return NaN; } - if(undirected){ - return 2 * graph.getLinksCount() / (nodes * (nodes - 1)); - } else { + if(directed){ return graph.getLinksCount() / (nodes * (nodes - 1)); + } else { + return 2 * graph.getLinksCount() / (nodes * (nodes - 1)); } } }; From 5c50ba1ef03852b5e6c74ef355fed4f98a4a95e9 Mon Sep 17 00:00:00 2001 From: anvaka Date: Thu, 6 Mar 2014 23:33:35 -0800 Subject: [PATCH 071/276] Constant layout returns stable after first iteration --- src/Layout/constant.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Layout/constant.js b/src/Layout/constant.js index 6d22a6a..21890c2 100644 --- a/src/Layout/constant.js +++ b/src/Layout/constant.js @@ -82,7 +82,7 @@ Viva.Graph.Layout.constant = function (graph, userSettings) { step : function () { updateNodePositions(); - return false; // no need to continue. + return true; // no need to continue. }, /** From 9cf0a2cbb2c9e883a435e1572c396b19a01c1561 Mon Sep 17 00:00:00 2001 From: anvaka Date: Fri, 7 Mar 2014 17:37:00 -0800 Subject: [PATCH 072/276] Using Object.create instead of {} Firefox has methods like `watch` on each object, which gives odd results when your node id is `watch`. --- src/Core/graph.js | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/src/Core/graph.js b/src/Core/graph.js index 6bdf3a5..401c5a3 100644 --- a/src/Core/graph.js +++ b/src/Core/graph.js @@ -22,7 +22,7 @@ Viva.Graph.graph = function () { // in terms of memory, but simplifies coding. Furthermore, the graph structure // is isolated from outter world, and can be changed to adjacency matrix later. - var nodes = {}, + var nodes = (typeof Object.create === 'function') ? Object.create(null) : {}, links = [], // Hash of multi-edges. Used to track ids of edges between same nodes multiEdges = {}, @@ -62,14 +62,6 @@ Viva.Graph.graph = function () { recordLinkChange = function (link, changeType) { // TODO: Could add change type verification; changes.push({link : link, changeType : changeType}); - }, - - isArray = function (value) { - return value && - typeof value === 'object' && - typeof value.length === 'number' && - typeof value.splice === 'function' && - !(value.propertyIsEnumerable('length')); }; /** @scope Viva.Graph.graph */ @@ -277,11 +269,8 @@ Viva.Graph.graph = function () { // TODO: could it be faster for nodes iteration if we had indexed access? // I.e. use array + 'for' iterator instead of dictionary + 'for .. in'? for (node in nodes) { - // For performance reasons you might want to sacrifice this sanity check: - if (nodes.hasOwnProperty(node)) { - if (callback(nodes[node])) { - return; // client doesn't want to proceed. return. - } + if (callback(nodes[node])) { + return; // client doesn't want to proceed. return. } } }, From 4b393ac8f68e93ff13087f7745762dc3a11cc133 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 5 Apr 2014 10:07:20 -0700 Subject: [PATCH 073/276] Fixed `constant layout not initialized` https://github.com/anvaka/VivaGraphJS/issues/74 --- dist/vivagraph.js | 54 ++++++++++++++++++------------------------ dist/vivagraph.min.js | 4 ++-- src/Layout/constant.js | 21 ++++++++-------- src/version.js | 2 +- 4 files changed, 36 insertions(+), 45 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 26e0903..5190581 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -7,7 +7,7 @@ Viva.Graph = Viva.Graph || {}; if (typeof module !== 'undefined' && module.exports) { module.exports = Viva; } -Viva.Graph.version = '0.5.4'; +Viva.Graph.version = '0.5.6'; /** * Extends target object with given fields/values in the options object. * Unlike jQuery's extend this method does not override target object @@ -1004,7 +1004,7 @@ Viva.Graph.graph = function () { // in terms of memory, but simplifies coding. Furthermore, the graph structure // is isolated from outter world, and can be changed to adjacency matrix later. - var nodes = {}, + var nodes = (typeof Object.create === 'function') ? Object.create(null) : {}, links = [], // Hash of multi-edges. Used to track ids of edges between same nodes multiEdges = {}, @@ -1044,14 +1044,6 @@ Viva.Graph.graph = function () { recordLinkChange = function (link, changeType) { // TODO: Could add change type verification; changes.push({link : link, changeType : changeType}); - }, - - isArray = function (value) { - return value && - typeof value === 'object' && - typeof value.length === 'number' && - typeof value.splice === 'function' && - !(value.propertyIsEnumerable('length')); }; /** @scope Viva.Graph.graph */ @@ -1259,11 +1251,8 @@ Viva.Graph.graph = function () { // TODO: could it be faster for nodes iteration if we had indexed access? // I.e. use array + 'for' iterator instead of dictionary + 'for .. in'? for (node in nodes) { - // For performance reasons you might want to sacrifice this sanity check: - if (nodes.hasOwnProperty(node)) { - if (callback(nodes[node])) { - return; // client doesn't want to proceed. return. - } + if (callback(nodes[node])) { + return; // client doesn't want to proceed. return. } } }, @@ -1393,16 +1382,20 @@ Viva.Graph.operations = function () { * Density 0 - graph has no edges. Runtime: O(1) * * @param graph represents oriented graph structure. + * @param directed (optional boolean) represents if the graph should be treated as a directed graph. * - * @returns density of the graph if graph has nodes. NaN otherwise + * @returns density of the graph if graph has nodes. NaN otherwise. Returns density for undirected graph by default but returns density for directed graph if a boolean 'true' is passed along with the graph. */ - density : function (graph) { + density : function (graph,directed) { var nodes = graph.getNodesCount(); if (nodes === 0) { return NaN; } - - return 2 * graph.getLinksCount() / (nodes * (nodes - 1)); + if(directed){ + return graph.getLinksCount() / (nodes * (nodes - 1)); + } else { + return 2 * graph.getLinksCount() / (nodes * (nodes - 1)); + } } }; }; @@ -2591,13 +2584,11 @@ Viva.Graph.Layout.constant = function (graph, userSettings) { if (position.y > graphRect.y2) { graphRect.y2 = position.y; } }, - layoutNodes = {}, + layoutNodes = typeof Object.create === 'function' ? Object.create(null) : {}, ensureNodeInitialized = function (node) { if (!node) { return; } - if (!layoutNodes[node.id]) { - layoutNodes[node.id] = placeNodeCallback(node); - } + layoutNodes[node.id] = placeNodeCallback(node); updateGraphRect(layoutNodes[node.id], graphRect); }, @@ -2615,17 +2606,18 @@ Viva.Graph.Layout.constant = function (graph, userSettings) { onGraphChanged = function(changes) { for (var i = 0; i < changes.length; ++i) { var change = changes[i]; - if (change.changeType === 'add' && change.node) { - ensureNodeInitialized(change.node); + if (change.node) { + if (change.changeType === 'add') { + ensureNodeInitialized(change.node); + } else { + delete layoutNodes[change.node.id]; + } } } - }, - - initLayout = function () { - updateNodePositions(); - graph.addEventListener('changed', onGraphChanged); }; + graph.addEventListener('changed', onGraphChanged); + return { /** * Attempts to layout graph within given number of iterations. @@ -2643,7 +2635,7 @@ Viva.Graph.Layout.constant = function (graph, userSettings) { step : function () { updateNodePositions(); - return false; // no need to continue. + return true; // no need to continue. }, /** diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 3c0f1f9..735f83f 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.4",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},P=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},N=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",P,!1):e.addEventListener("DOMMouseScroll",P,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",P,!1):e.removeEventListener("DOMMouseScroll",P,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),N(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e={},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e){var t=e.getNodesCount();return 0===t?0/0:2*e.getLinksCount()/(t*(t-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,d=Math.sqrt(f*f+c*c);d>r&&(u.velocity.x=r*f/d,u.velocity.y=r*c/d),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};r="number"==typeof r?r:1;var o=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,r);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02,springTransform:function(){},timeStep:20,stableThreshold:.001});var n=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),r=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),i=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),o=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),a=new Viva.Graph.Rect,u=Viva.random("ted.com",103,114,101,97,116),s={},f=function(e){if(e.position)return e.position;var n=(a.x1+a.x2)/2,r=(a.y1+a.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],f=o.fromId!==e.id?s[o.fromId]:s[o.toId];f&&f.location&&(n=f.location.x,r=f.location.y)}return{x:n+u.next(i)-i/2,y:r+u.next(i)-i/2}},c=function(e){return s[e]},d=function(e){s[e]=null,delete s[e]},l={},h=function(t){var n=c(t);n.mass=1+e.getLinks(t).length/3},v=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},p=function(e){return e.isPinned},m=function(t){var r=c(t);if(!r){var i=e.getNode(t);if(!i)return;r=new Viva.Graph.Physics.Body,s[t]=r;var o=f(i);r.loc(o),h(t),v(i)&&(r.isPinned=!0),n.addBody(r)}},g=function(e){m(e.id)},y=function(t){var r=c(t.id);r&&(d(t.id),n.removeBody(r),0===e.getNodesCount()&&(a.x1=a.y1=0,a.x2=a.y2=0))},x=function(e){h(e.fromId),h(e.toId);var r=c(e.fromId),i=c(e.toId),o=n.addSpring(r,i,-1,e.weight);t.springTransform(e,o),l[e.id]=o},w=function(t){var r=l[t.id];if(r){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&h(i.id),o&&h(o.id),delete l[t.id],n.removeSpring(r)}},V=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&m(n.node.id),n.link&&x(n.link)):"remove"===n.changeType&&(n.node&&y(n.node),n.link&&w(n.link))}},b=function(){e.forEachNode(g),e.forEachLink(x),e.addEventListener("changed",V)},P=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in s)if(s.hasOwnProperty(o)){var u=s[o];p(u)?(u.location.x=u.prevLocation.x,u.location.y=u.prevLocation.y):(u.prevLocation.x=u.location.x,u.prevLocation.y=u.location.y),t>u.location.x&&(t=u.location.x),u.location.x>r&&(r=u.location.x),n>u.location.y&&(n=u.location.y),u.location.y>i&&(i=u.location.y)}a.x1=t,a.x2=r,a.y1=n,a.y2=i}};return n.setSpringForce(i),n.setNbodyForce(r),n.setDragForce(o),b(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=n.run(t.timeStep);return P(),t.stableThreshold>e},isNodePinned:function(e){var t=c(e.id);return t?p(t):void 0},pinNode:function(e,t){var n=c(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=c(e);return t||(m(e),t=c(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=c(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return a},dispose:function(){e.removeEventListener("change",V)},springLength:function(e){return 1===arguments.length?(i.options({length:e}),this):i.options().length},springCoeff:function(e){return 1===arguments.length?(i.options({coeff:e}),this):i.options().coeff},gravity:function(e){return 1===arguments.length?(r.options({gravity:e}),this):r.options().gravity},theta:function(e){return 1===arguments.length?(r.options({theta:e}),this):r.options().theta},drag:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a={},u=function(e){e&&(a[e.id]||(a[e.id]=i(e)),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType&&n.node&&u(n.node)}};return{run:function(){this.step()},step:function(){return s(),!1},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,d=!0,l=0,h=0,v=!1,p=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return v=u.step()&&!p,V(),!v},P=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(l=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},N=function(){v=!1,i.restart()},E=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX,g.offsetY),d=!1},L=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),p=!0,N()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),p=!0,V()},onStop:function(){u.pinNode(e,t),p=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),d&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(d=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},D=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);N()},R=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",D),o=null)},z=function(e,t){if(!t){var n=Viva.Graph.Utils.getDimension(f);t={x:n.width/2,y:n.height/2}}var r=Math.pow(1.4,e?-.2:.2);g.scale=s.scale(r,t),V(),w.fire("scale",g.scale)},B=function(){x.on("resize",R),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){z(0>t,n)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",D)},Y=function(){c=!1,O(),F(),x.stop("resize",R),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),E(),G(),C(),B(),c=!0),P(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},zoomOut:function(){z(!0)},zoomIn:function(){z(!1)},moveTo:function(e,t){s.graphCenterChanged(g.offsetX-e*g.scale,g.offsetY-t*g.scale),V()},getGraphics:function(){return s},dispose:function(){Y()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph(); -for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},d=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},l=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?d(e):(d=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,l()},translateRel:function(e,r){t+=e,n+=r,l()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,l()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),d=f.attr("id"),l=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&d===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&l===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i,o=1,a={},u={},s=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},f=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},c=function(){return Viva.Graph.svg("line").attr("stroke","#999")},d=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},l=function(e){e.fire("rescaled")},h={x:0,y:0},v={x:0,y:0},p={x:0,y:0},m=function(){if(e){var t="matrix("+o+", 0, 0,"+o+","+n+","+r+")";e.attr("transform",t)}},g={getNodeUI:function(e){return a[e]},getLinkUI:function(e){return u[e]},node:function(e){return"function"==typeof e?(s=e,this):void 0},link:function(e){return"function"==typeof e?(c=e,this):void 0},placeNode:function(e){return f=e,this},placeLink:function(e){return d=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,m()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(i,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(i).translate(-u.x,-u.y),f=e.getCTM().multiply(s);o=f.a,n=f.e,r=f.f;var c="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",c),l(this),o},resetScale:function(){o=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),l(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),m(),"function"==typeof i&&i(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(t,n){var r=c(t);if(r)return r.position=n,r.link=t,u[t.id]=r,e.childElementCount>0?e.insertBefore(r,e.firstChild):e.appendChild(r),r},releaseLink:function(t){var n=u[t.id];n&&(e.removeChild(n),delete u[t.id])},addNode:function(t,n){var r=s(t);if(r)return r.position=n,r.node=t,a[t.id]=r,e.appendChild(r),r},releaseNode:function(t){var n=a[t.id];n&&(e.removeChild(n),delete a[t.id])},renderNodes:function(){for(var e in a)if(a.hasOwnProperty(e)){var t=a[e];h.x=t.position.x,h.y=t.position.y,f(t,h,t.node)}},renderLinks:function(){for(var e in u)if(u.hasOwnProperty(e)){var t=u[e];v.x=t.position.from.x,v.y=t.position.from.y,p.x=t.position.to.x,p.y=t.position.to.y,d(t,v,p,t.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):i=e),t},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(g).extend(),g},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,d=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(d.x)+" "+Math.round(d.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),l=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),v=new Float32Array(h),p=new Uint32Array(h),m=0,g=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(p),v=t,p=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(l,d),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;v[n*f]=t.x,v[n*f+1]=t.y,v[n*f+2]=e.size,p[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(p,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,d=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),v=0,p=new ArrayBuffer(16*d),m=new Float32Array(p),g=new Uint32Array(p),y=function(){if((v+1)*d>p.byteLength){var e=new ArrayBuffer(2*p.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,p=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,l),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),v+=1,o=e.id},removeLink:function(e){v>0&&(v-=1),v>e.id&&v>0&&r.copyArrayPart(g,e.id*c,v*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,p,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*v),o=v-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},d=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},l=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},v=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},p=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=l(e),o={offset:e};r.textureNumber>=s.length&&d();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=l(t.offset),r=l(o);p(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],v(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){v(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,d=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),l=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,v=0,p=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(l,d),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;p[n]=t.x-e.size,p[n+1]=t.y-e.size,p[n+2]=4*e._offset,p[n+3]=t.x+e.size,p[n+4]=t.y-e.size,p[n+5]=4*e._offset+1,p[n+6]=t.x-e.size,p[n+7]=t.y+e.size,p[n+8]=4*e._offset+2,p[n+9]=t.x-e.size,p[n+10]=t.y+e.size,p[n+11]=4*e._offset+2,p[n+12]=t.x+e.size,p[n+13]=t.y-e.size,p[n+14]=4*e._offset+1,p[n+15]=t.x+e.size,p[n+16]=t.y+e.size,p[n+17]=4*e._offset+3},createNode:function(t){p=i.extendArray(p,v,c),v+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){v>0&&(v-=1),v>t.id&&v>0&&(t.src&&e.remove(t.src),i.copyArrayPart(p,t.id*c,v*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,p,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*v)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f=0,c=0,d=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],l=[],h=[],v={},p={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(d),g.updateTransform(d)},V=function(){d=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},P=function(e){e.fire("rescaled")},N={getLinkUI:function(e){return p[e]},getNodeUI:function(e){return v[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return a=e,this},placeLink:function(e){return u=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){c>0&&m.render(),f>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(e,t){d[12]=2*e/i-1,d[13]=1-2*t/o,w()},addLink:function(e,t){var n=c++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,p[e.id]=r,r},addNode:function(e,t){var n=f++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),l[n]=r,v[e.id]=r,r},translateRel:function(e,t){d[12]+=2*d[0]*e/i/d[0],d[13]-=2*d[5]*t/o/d[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=d[12],r-=d[13],d[12]+=n*(1-e),d[13]+=r*(1-e),d[0]*=e,d[5]*=e,w(),P(this),d[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var f="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(f),f}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof s&&s(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){c>0&&(c-=1);var t=p[e.id];delete p[e.id],m.removeLink(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=h[c];h[n]=r,r.id=n}},releaseNode:function(e){f>0&&(f-=1);var t=v[e.id];delete v[e.id],g.removeNode(t);var n=t.id;if(f>n){if(0===f||f===n)return;var r=l[f];l[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;f>t;++t){var n=l[t];e.x=n.position.x,e.y=-n.position.y,a&&a(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;c>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,u&&u(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):s=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-d[12])/d[0],e.y=(e.y-d[13])/d[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;f>n;++n)if(t(l[n],e.x,e.y))return l[n].node;return null}};return Viva.Graph.Utils.events(N).extend(),N},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},i=function(t){return e.getNodeAtClientPos(t,r)},o=null,a=[],u=[],s=[],f=[],c=[],d=[],l=[],h=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},p=function(e){return v(e),!1},m=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(e){var r={x:0,y:0},g=null,y=+new Date,x=function(e){m(c,[g,e]),r.x=e.clientX,r.y=e.clientY},w=function(){h.stop("mousemove",x),h.stop("mouseup",w)},V=function(){n=e.getBoundingClientRect()};window.addEventListener("resize",V),V(),e.addEventListener("mousemove",function(e){if(!o){var t,s=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,t=i(r),t&&g!==t?(g=t,s=s||m(a,[g])):null===t&&g!==t&&(s=s||m(u,[g]),g=null),s&&v(e)}}),e.addEventListener("mousedown",function(e){var o,a=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]?(a=m(s,o),h.on("mousemove",x),h.on("mouseup",w),t=window.document.onselectstart,window.document.onselectstart=p,g=o[0]):g=null,a&&v(e)}),e.addEventListener("mouseup",function(e){var o,a=+new Date;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]&&(window.document.onselectstart=t,400>a-y&&o[0]===g?m(l,o):m(d,o),y=a,m(f,o)&&v(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&l.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file +var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.6",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},N=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},P=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",N,!1):e.addEventListener("DOMMouseScroll",N,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",N,!1):e.removeEventListener("DOMMouseScroll",N,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return P(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),P(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e="function"==typeof Object.create?Object.create(null):{},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e,t){var n=e.getNodesCount();return 0===n?0/0:t?e.getLinksCount()/(n*(n-1)):2*e.getLinksCount()/(n*(n-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,d=Math.sqrt(f*f+c*c);d>r&&(u.velocity.x=r*f/d,u.velocity.y=r*c/d),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};r="number"==typeof r?r:1;var o=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,r);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02,springTransform:function(){},timeStep:20,stableThreshold:.001});var n=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),r=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),i=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),o=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),a=new Viva.Graph.Rect,u=Viva.random("ted.com",103,114,101,97,116),s={},f=function(e){if(e.position)return e.position;var n=(a.x1+a.x2)/2,r=(a.y1+a.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],f=o.fromId!==e.id?s[o.fromId]:s[o.toId];f&&f.location&&(n=f.location.x,r=f.location.y)}return{x:n+u.next(i)-i/2,y:r+u.next(i)-i/2}},c=function(e){return s[e]},d=function(e){s[e]=null,delete s[e]},l={},h=function(t){var n=c(t);n.mass=1+e.getLinks(t).length/3},v=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},p=function(e){return e.isPinned},m=function(t){var r=c(t);if(!r){var i=e.getNode(t);if(!i)return;r=new Viva.Graph.Physics.Body,s[t]=r;var o=f(i);r.loc(o),h(t),v(i)&&(r.isPinned=!0),n.addBody(r)}},g=function(e){m(e.id)},y=function(t){var r=c(t.id);r&&(d(t.id),n.removeBody(r),0===e.getNodesCount()&&(a.x1=a.y1=0,a.x2=a.y2=0))},x=function(e){h(e.fromId),h(e.toId);var r=c(e.fromId),i=c(e.toId),o=n.addSpring(r,i,-1,e.weight);t.springTransform(e,o),l[e.id]=o},w=function(t){var r=l[t.id];if(r){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&h(i.id),o&&h(o.id),delete l[t.id],n.removeSpring(r)}},V=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&m(n.node.id),n.link&&x(n.link)):"remove"===n.changeType&&(n.node&&y(n.node),n.link&&w(n.link))}},b=function(){e.forEachNode(g),e.forEachLink(x),e.addEventListener("changed",V)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in s)if(s.hasOwnProperty(o)){var u=s[o];p(u)?(u.location.x=u.prevLocation.x,u.location.y=u.prevLocation.y):(u.prevLocation.x=u.location.x,u.prevLocation.y=u.location.y),t>u.location.x&&(t=u.location.x),u.location.x>r&&(r=u.location.x),n>u.location.y&&(n=u.location.y),u.location.y>i&&(i=u.location.y)}a.x1=t,a.x2=r,a.y1=n,a.y2=i}};return n.setSpringForce(i),n.setNbodyForce(r),n.setDragForce(o),b(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=n.run(t.timeStep);return N(),t.stableThreshold>e},isNodePinned:function(e){var t=c(e.id);return t?p(t):void 0},pinNode:function(e,t){var n=c(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=c(e);return t||(m(e),t=c(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=c(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return a},dispose:function(){e.removeEventListener("change",V)},springLength:function(e){return 1===arguments.length?(i.options({length:e}),this):i.options().length},springCoeff:function(e){return 1===arguments.length?(i.options({coeff:e}),this):i.options().coeff},gravity:function(e){return 1===arguments.length?(r.options({gravity:e}),this):r.options().gravity},theta:function(e){return 1===arguments.length?(r.options({theta:e}),this):r.options().theta},drag:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a="function"==typeof Object.create?Object.create(null):{},u=function(e){e&&(a[e.id]=i(e),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];n.node&&("add"===n.changeType?u(n.node):delete a[n.node.id])}};return e.addEventListener("changed",f),{run:function(){this.step()},step:function(){return s(),!0},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,d=!0,l=0,h=0,v=!1,p=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return v=u.step()&&!p,V(),!v},N=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(l=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},P=function(){v=!1,i.restart()},E=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX,g.offsetY),d=!1},L=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),p=!0,P()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),p=!0,V()},onStop:function(){u.pinNode(e,t),p=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),d&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(d=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},D=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);P()},R=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",D),o=null)},z=function(e,t){if(!t){var n=Viva.Graph.Utils.getDimension(f);t={x:n.width/2,y:n.height/2}}var r=Math.pow(1.4,e?-.2:.2);g.scale=s.scale(r,t),V(),w.fire("scale",g.scale)},B=function(){x.on("resize",R),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){z(0>t,n)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",D)},Y=function(){c=!1,O(),F(),x.stop("resize",R),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),E(),G(),C(),B(),c=!0),N(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},zoomOut:function(){z(!0)},zoomIn:function(){z(!1)},moveTo:function(e,t){s.graphCenterChanged(g.offsetX-e*g.scale,g.offsetY-t*g.scale),V()},getGraphics:function(){return s},dispose:function(){Y()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"}; +var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},d=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},l=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?d(e):(d=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,l()},translateRel:function(e,r){t+=e,n+=r,l()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,l()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),d=f.attr("id"),l=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&d===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&l===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i,o=1,a={},u={},s=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},f=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},c=function(){return Viva.Graph.svg("line").attr("stroke","#999")},d=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},l=function(e){e.fire("rescaled")},h={x:0,y:0},v={x:0,y:0},p={x:0,y:0},m=function(){if(e){var t="matrix("+o+", 0, 0,"+o+","+n+","+r+")";e.attr("transform",t)}},g={getNodeUI:function(e){return a[e]},getLinkUI:function(e){return u[e]},node:function(e){return"function"==typeof e?(s=e,this):void 0},link:function(e){return"function"==typeof e?(c=e,this):void 0},placeNode:function(e){return f=e,this},placeLink:function(e){return d=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,m()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(i,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(i).translate(-u.x,-u.y),f=e.getCTM().multiply(s);o=f.a,n=f.e,r=f.f;var c="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",c),l(this),o},resetScale:function(){o=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),l(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),m(),"function"==typeof i&&i(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(t,n){var r=c(t);if(r)return r.position=n,r.link=t,u[t.id]=r,e.childElementCount>0?e.insertBefore(r,e.firstChild):e.appendChild(r),r},releaseLink:function(t){var n=u[t.id];n&&(e.removeChild(n),delete u[t.id])},addNode:function(t,n){var r=s(t);if(r)return r.position=n,r.node=t,a[t.id]=r,e.appendChild(r),r},releaseNode:function(t){var n=a[t.id];n&&(e.removeChild(n),delete a[t.id])},renderNodes:function(){for(var e in a)if(a.hasOwnProperty(e)){var t=a[e];h.x=t.position.x,h.y=t.position.y,f(t,h,t.node)}},renderLinks:function(){for(var e in u)if(u.hasOwnProperty(e)){var t=u[e];v.x=t.position.from.x,v.y=t.position.from.y,p.x=t.position.to.x,p.y=t.position.to.y,d(t,v,p,t.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):i=e),t},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(g).extend(),g},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,d=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(d.x)+" "+Math.round(d.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),l=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),v=new Float32Array(h),p=new Uint32Array(h),m=0,g=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(p),v=t,p=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(l,d),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;v[n*f]=t.x,v[n*f+1]=t.y,v[n*f+2]=e.size,p[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(p,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,d=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),v=0,p=new ArrayBuffer(16*d),m=new Float32Array(p),g=new Uint32Array(p),y=function(){if((v+1)*d>p.byteLength){var e=new ArrayBuffer(2*p.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,p=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,l),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),v+=1,o=e.id},removeLink:function(e){v>0&&(v-=1),v>e.id&&v>0&&r.copyArrayPart(g,e.id*c,v*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,p,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*v),o=v-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},d=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},l=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},v=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},p=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=l(e),o={offset:e};r.textureNumber>=s.length&&d();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=l(t.offset),r=l(o);p(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],v(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){v(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,d=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),l=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,v=0,p=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(l,d),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;p[n]=t.x-e.size,p[n+1]=t.y-e.size,p[n+2]=4*e._offset,p[n+3]=t.x+e.size,p[n+4]=t.y-e.size,p[n+5]=4*e._offset+1,p[n+6]=t.x-e.size,p[n+7]=t.y+e.size,p[n+8]=4*e._offset+2,p[n+9]=t.x-e.size,p[n+10]=t.y+e.size,p[n+11]=4*e._offset+2,p[n+12]=t.x+e.size,p[n+13]=t.y-e.size,p[n+14]=4*e._offset+1,p[n+15]=t.x+e.size,p[n+16]=t.y+e.size,p[n+17]=4*e._offset+3},createNode:function(t){p=i.extendArray(p,v,c),v+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){v>0&&(v-=1),v>t.id&&v>0&&(t.src&&e.remove(t.src),i.copyArrayPart(p,t.id*c,v*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,p,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*v)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f=0,c=0,d=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],l=[],h=[],v={},p={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(d),g.updateTransform(d)},V=function(){d=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},N=function(e){e.fire("rescaled")},P={getLinkUI:function(e){return p[e]},getNodeUI:function(e){return v[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return a=e,this},placeLink:function(e){return u=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){c>0&&m.render(),f>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(e,t){d[12]=2*e/i-1,d[13]=1-2*t/o,w()},addLink:function(e,t){var n=c++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,p[e.id]=r,r},addNode:function(e,t){var n=f++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),l[n]=r,v[e.id]=r,r},translateRel:function(e,t){d[12]+=2*d[0]*e/i/d[0],d[13]-=2*d[5]*t/o/d[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=d[12],r-=d[13],d[12]+=n*(1-e),d[13]+=r*(1-e),d[0]*=e,d[5]*=e,w(),N(this),d[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var f="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(f),f}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof s&&s(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){c>0&&(c-=1);var t=p[e.id];delete p[e.id],m.removeLink(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=h[c];h[n]=r,r.id=n}},releaseNode:function(e){f>0&&(f-=1);var t=v[e.id];delete v[e.id],g.removeNode(t);var n=t.id;if(f>n){if(0===f||f===n)return;var r=l[f];l[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;f>t;++t){var n=l[t];e.x=n.position.x,e.y=-n.position.y,a&&a(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;c>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,u&&u(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):s=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-d[12])/d[0],e.y=(e.y-d[13])/d[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;f>n;++n)if(t(l[n],e.x,e.y))return l[n].node;return null}};return Viva.Graph.Utils.events(P).extend(),P},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},i=function(t){return e.getNodeAtClientPos(t,r)},o=null,a=[],u=[],s=[],f=[],c=[],d=[],l=[],h=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},p=function(e){return v(e),!1},m=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(e){var r={x:0,y:0},g=null,y=+new Date,x=function(e){m(c,[g,e]),r.x=e.clientX,r.y=e.clientY},w=function(){h.stop("mousemove",x),h.stop("mouseup",w)},V=function(){n=e.getBoundingClientRect()};window.addEventListener("resize",V),V(),e.addEventListener("mousemove",function(e){if(!o){var t,s=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,t=i(r),t&&g!==t?(g=t,s=s||m(a,[g])):null===t&&g!==t&&(s=s||m(u,[g]),g=null),s&&v(e)}}),e.addEventListener("mousedown",function(e){var o,a=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]?(a=m(s,o),h.on("mousemove",x),h.on("mouseup",w),t=window.document.onselectstart,window.document.onselectstart=p,g=o[0]):g=null,a&&v(e)}),e.addEventListener("mouseup",function(e){var o,a=+new Date;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]&&(window.document.onselectstart=t,400>a-y&&o[0]===g?m(l,o):m(d,o),y=a,m(f,o)&&v(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&l.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file diff --git a/src/Layout/constant.js b/src/Layout/constant.js index 21890c2..3eca118 100644 --- a/src/Layout/constant.js +++ b/src/Layout/constant.js @@ -30,13 +30,11 @@ Viva.Graph.Layout.constant = function (graph, userSettings) { if (position.y > graphRect.y2) { graphRect.y2 = position.y; } }, - layoutNodes = {}, + layoutNodes = typeof Object.create === 'function' ? Object.create(null) : {}, ensureNodeInitialized = function (node) { if (!node) { return; } - if (!layoutNodes[node.id]) { - layoutNodes[node.id] = placeNodeCallback(node); - } + layoutNodes[node.id] = placeNodeCallback(node); updateGraphRect(layoutNodes[node.id], graphRect); }, @@ -54,17 +52,18 @@ Viva.Graph.Layout.constant = function (graph, userSettings) { onGraphChanged = function(changes) { for (var i = 0; i < changes.length; ++i) { var change = changes[i]; - if (change.changeType === 'add' && change.node) { - ensureNodeInitialized(change.node); + if (change.node) { + if (change.changeType === 'add') { + ensureNodeInitialized(change.node); + } else { + delete layoutNodes[change.node.id]; + } } } - }, - - initLayout = function () { - updateNodePositions(); - graph.addEventListener('changed', onGraphChanged); }; + graph.addEventListener('changed', onGraphChanged); + return { /** * Attempts to layout graph within given number of iterations. diff --git a/src/version.js b/src/version.js index 950cac7..07fd4c2 100644 --- a/src/version.js +++ b/src/version.js @@ -1 +1 @@ -Viva.Graph.version = '0.5.5'; +Viva.Graph.version = '0.5.6'; From e9c220fbdc1ecc6fdca90b9484aefd55cba181d0 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 5 Apr 2014 10:10:37 -0700 Subject: [PATCH 074/276] 0.5.6 --- CHANGELOG | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index a51d39c..ab0c1ad 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,11 @@ +v0.5.6 + date: Apr 05, 2014 + - Using Object.create where possible to avoid node id collision with + standard object property names (e.g. `constructor`) + - Fixed bug in constant layout + v0.5.5 - date: Feb 22, 2013 + date: Feb 22, 2014 - Stable threshold can now be configured via options (Tnanks to @grnadav) v0.5.4 From 3cfc2f018032c8c10692490f23d61a93c8a6d09c Mon Sep 17 00:00:00 2001 From: anvaka Date: Fri, 18 Apr 2014 08:33:51 -0700 Subject: [PATCH 075/276] 0.5.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fda95d0..8144c6c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.5.5", + "version": "0.5.6", "description": "Graph Drawing Library", "main": "dist/vivagraph", "directories": { From 0b0ad33be30da75260a03cb3ba80f196942e5bb6 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 19 Apr 2014 01:56:12 -0700 Subject: [PATCH 076/276] Making linter happier --- src/View/renderer.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/View/renderer.js b/src/View/renderer.js index d3cc489..103b985 100644 --- a/src/View/renderer.js +++ b/src/View/renderer.js @@ -290,8 +290,8 @@ Viva.Graph.View.renderer = function (graph, settings) { if (!scrollPoint) { var containerSize = Viva.Graph.Utils.getDimension(container); scrollPoint = { - x: containerSize.width/2, - y: containerSize.height/2 + x: containerSize.width/2, + y: containerSize.height/2 }; } var scaleFactor = Math.pow(1 + 0.4, out ? -0.2 : 0.2); @@ -315,7 +315,7 @@ Viva.Graph.View.renderer = function (graph, settings) { }); containerDrag.onScroll(function (e, scaleOffset, scrollPoint) { - scale(scaleOffset < 0, scrollPoint); + scale(scaleOffset < 0, scrollPoint); }); graph.forEachNode(listenNodeEvents); @@ -394,26 +394,26 @@ Viva.Graph.View.renderer = function (graph, settings) { }, zoomOut: function () { - scale(true); + scale(true); }, zoomIn: function () { - scale(false); + scale(false); }, /** * Centers renderer at x,y graph's coordinates */ moveTo: function (x, y) { - graphics.graphCenterChanged(transform.offsetX - x * transform.scale, transform.offsetY - y * transform.scale); - renderGraph(); + graphics.graphCenterChanged(transform.offsetX - x * transform.scale, transform.offsetY - y * transform.scale); + renderGraph(); }, /** * Gets current graphics object */ getGraphics: function () { - return graphics; + return graphics; }, /** From 90b0f4355835508c5bf7a6570f7576cf72c9be45 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 20 Apr 2014 11:36:10 -0700 Subject: [PATCH 077/276] Let users disable graph interaction --- src/View/renderer.js | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/src/View/renderer.js b/src/View/renderer.js index 103b985..908da75 100644 --- a/src/View/renderer.js +++ b/src/View/renderer.js @@ -25,6 +25,9 @@ Viva.Graph.View = Viva.Graph.View || {}; * // might depend on it. * container : document.body, * + * // Defines whether graph can respond to use input + * interactive: true, + * * // Layout algorithm to be used. The algorithm is expected to comply with defined * // interface and is expected to be iterative. Renderer will use it then to calculate * // grpaph's layout. For examples of the interface refer to Viva.Graph.Layout.forceDirected() @@ -50,6 +53,7 @@ Viva.Graph.View.renderer = function (graph, settings) { var layout = settings.layout, graphics = settings.graphics, container = settings.container, + interactive = settings.interactive !== undefined ? settings.interactive : true, inputManager, animationTimer, rendererInitialized = false, @@ -173,6 +177,10 @@ Viva.Graph.View.renderer = function (graph, settings) { listenNodeEvents = function (node) { var wasPinned = false; + var nodeInteractive = (typeof interactive === 'string' && interactive.indexOf('node') !== -1) || interactive; + if (!nodeInteractive) { + return; + } // TODO: This may not be memory efficient. Consider reusing handlers object. inputManager.bindDragNDrop(node, { @@ -305,18 +313,24 @@ Viva.Graph.View.renderer = function (graph, settings) { windowEvents.on('resize', onWindowResized); releaseContainerDragManager(); - containerDrag = Viva.Graph.Utils.dragndrop(container); - containerDrag.onDrag(function (e, offset) { - viewPortOffset.x += offset.x; - viewPortOffset.y += offset.y; - graphics.translateRel(offset.x, offset.y); + var canDrag = (typeof interactive === 'string' && interactive.indexOf('drag') !== -1) || interactive; + if (canDrag) { + containerDrag = Viva.Graph.Utils.dragndrop(container); + containerDrag.onDrag(function (e, offset) { + viewPortOffset.x += offset.x; + viewPortOffset.y += offset.y; + graphics.translateRel(offset.x, offset.y); - renderGraph(); - }); + renderGraph(); + }); + } - containerDrag.onScroll(function (e, scaleOffset, scrollPoint) { - scale(scaleOffset < 0, scrollPoint); - }); + var canScroll = (typeof interactive === 'string' && interactive.indexOf('scroll') !== -1) || interactive; + if (canScroll) { + containerDrag.onScroll(function (e, scaleOffset, scrollPoint) { + scale(scaleOffset < 0, scrollPoint); + }); + } graph.forEachNode(listenNodeEvents); From 8764e97796c7b2581979b4a0971c58864b7b3b07 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 20 Apr 2014 11:57:07 -0700 Subject: [PATCH 078/276] Allowing disable user input on entire graph --- dist/vivagraph.js | 53 +++++++++++++++++++++++++++---------------- dist/vivagraph.min.js | 4 ++-- src/Utils/events.js | 2 +- src/version.js | 2 +- 4 files changed, 38 insertions(+), 23 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 5190581..11fd719 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -7,7 +7,7 @@ Viva.Graph = Viva.Graph || {}; if (typeof module !== 'undefined' && module.exports) { module.exports = Viva; } -Viva.Graph.version = '0.5.6'; +Viva.Graph.version = '0.5.7'; /** * Extends target object with given fields/values in the options object. * Unlike jQuery's extend this method does not override target object @@ -360,7 +360,8 @@ Viva.Graph.Utils.events = function (element) { return eventuality(element); } }; -};/** +}; +/** * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com */ @@ -2761,6 +2762,9 @@ Viva.Graph.View = Viva.Graph.View || {}; * // might depend on it. * container : document.body, * + * // Defines whether graph can respond to use input + * interactive: true, + * * // Layout algorithm to be used. The algorithm is expected to comply with defined * // interface and is expected to be iterative. Renderer will use it then to calculate * // grpaph's layout. For examples of the interface refer to Viva.Graph.Layout.forceDirected() @@ -2786,6 +2790,7 @@ Viva.Graph.View.renderer = function (graph, settings) { var layout = settings.layout, graphics = settings.graphics, container = settings.container, + interactive = settings.interactive !== undefined ? settings.interactive : true, inputManager, animationTimer, rendererInitialized = false, @@ -2909,6 +2914,10 @@ Viva.Graph.View.renderer = function (graph, settings) { listenNodeEvents = function (node) { var wasPinned = false; + var nodeInteractive = (typeof interactive === 'string' && interactive.indexOf('node') !== -1) || interactive; + if (!nodeInteractive) { + return; + } // TODO: This may not be memory efficient. Consider reusing handlers object. inputManager.bindDragNDrop(node, { @@ -3026,8 +3035,8 @@ Viva.Graph.View.renderer = function (graph, settings) { if (!scrollPoint) { var containerSize = Viva.Graph.Utils.getDimension(container); scrollPoint = { - x: containerSize.width/2, - y: containerSize.height/2 + x: containerSize.width/2, + y: containerSize.height/2 }; } var scaleFactor = Math.pow(1 + 0.4, out ? -0.2 : 0.2); @@ -3041,18 +3050,24 @@ Viva.Graph.View.renderer = function (graph, settings) { windowEvents.on('resize', onWindowResized); releaseContainerDragManager(); - containerDrag = Viva.Graph.Utils.dragndrop(container); - containerDrag.onDrag(function (e, offset) { - viewPortOffset.x += offset.x; - viewPortOffset.y += offset.y; - graphics.translateRel(offset.x, offset.y); + var canDrag = (typeof interactive === 'string' && interactive.indexOf('drag') !== -1) || interactive; + if (canDrag) { + containerDrag = Viva.Graph.Utils.dragndrop(container); + containerDrag.onDrag(function (e, offset) { + viewPortOffset.x += offset.x; + viewPortOffset.y += offset.y; + graphics.translateRel(offset.x, offset.y); - renderGraph(); - }); + renderGraph(); + }); + } - containerDrag.onScroll(function (e, scaleOffset, scrollPoint) { - scale(scaleOffset < 0, scrollPoint); - }); + var canScroll = (typeof interactive === 'string' && interactive.indexOf('scroll') !== -1) || interactive; + if (canScroll) { + containerDrag.onScroll(function (e, scaleOffset, scrollPoint) { + scale(scaleOffset < 0, scrollPoint); + }); + } graph.forEachNode(listenNodeEvents); @@ -3130,26 +3145,26 @@ Viva.Graph.View.renderer = function (graph, settings) { }, zoomOut: function () { - scale(true); + scale(true); }, zoomIn: function () { - scale(false); + scale(false); }, /** * Centers renderer at x,y graph's coordinates */ moveTo: function (x, y) { - graphics.graphCenterChanged(transform.offsetX - x * transform.scale, transform.offsetY - y * transform.scale); - renderGraph(); + graphics.graphCenterChanged(transform.offsetX - x * transform.scale, transform.offsetY - y * transform.scale); + renderGraph(); }, /** * Gets current graphics object */ getGraphics: function () { - return graphics; + return graphics; }, /** diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 735f83f..abd94a0 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.6",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},N=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},P=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",N,!1):e.addEventListener("DOMMouseScroll",N,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",N,!1):e.removeEventListener("DOMMouseScroll",N,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return P(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),P(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e="function"==typeof Object.create?Object.create(null):{},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e,t){var n=e.getNodesCount();return 0===n?0/0:t?e.getLinksCount()/(n*(n-1)):2*e.getLinksCount()/(n*(n-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,d=Math.sqrt(f*f+c*c);d>r&&(u.velocity.x=r*f/d,u.velocity.y=r*c/d),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};r="number"==typeof r?r:1;var o=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,r);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02,springTransform:function(){},timeStep:20,stableThreshold:.001});var n=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),r=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),i=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),o=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),a=new Viva.Graph.Rect,u=Viva.random("ted.com",103,114,101,97,116),s={},f=function(e){if(e.position)return e.position;var n=(a.x1+a.x2)/2,r=(a.y1+a.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],f=o.fromId!==e.id?s[o.fromId]:s[o.toId];f&&f.location&&(n=f.location.x,r=f.location.y)}return{x:n+u.next(i)-i/2,y:r+u.next(i)-i/2}},c=function(e){return s[e]},d=function(e){s[e]=null,delete s[e]},l={},h=function(t){var n=c(t);n.mass=1+e.getLinks(t).length/3},v=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},p=function(e){return e.isPinned},m=function(t){var r=c(t);if(!r){var i=e.getNode(t);if(!i)return;r=new Viva.Graph.Physics.Body,s[t]=r;var o=f(i);r.loc(o),h(t),v(i)&&(r.isPinned=!0),n.addBody(r)}},g=function(e){m(e.id)},y=function(t){var r=c(t.id);r&&(d(t.id),n.removeBody(r),0===e.getNodesCount()&&(a.x1=a.y1=0,a.x2=a.y2=0))},x=function(e){h(e.fromId),h(e.toId);var r=c(e.fromId),i=c(e.toId),o=n.addSpring(r,i,-1,e.weight);t.springTransform(e,o),l[e.id]=o},w=function(t){var r=l[t.id];if(r){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&h(i.id),o&&h(o.id),delete l[t.id],n.removeSpring(r)}},V=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&m(n.node.id),n.link&&x(n.link)):"remove"===n.changeType&&(n.node&&y(n.node),n.link&&w(n.link))}},b=function(){e.forEachNode(g),e.forEachLink(x),e.addEventListener("changed",V)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in s)if(s.hasOwnProperty(o)){var u=s[o];p(u)?(u.location.x=u.prevLocation.x,u.location.y=u.prevLocation.y):(u.prevLocation.x=u.location.x,u.prevLocation.y=u.location.y),t>u.location.x&&(t=u.location.x),u.location.x>r&&(r=u.location.x),n>u.location.y&&(n=u.location.y),u.location.y>i&&(i=u.location.y)}a.x1=t,a.x2=r,a.y1=n,a.y2=i}};return n.setSpringForce(i),n.setNbodyForce(r),n.setDragForce(o),b(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=n.run(t.timeStep);return N(),t.stableThreshold>e},isNodePinned:function(e){var t=c(e.id);return t?p(t):void 0},pinNode:function(e,t){var n=c(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=c(e);return t||(m(e),t=c(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=c(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return a},dispose:function(){e.removeEventListener("change",V)},springLength:function(e){return 1===arguments.length?(i.options({length:e}),this):i.options().length},springCoeff:function(e){return 1===arguments.length?(i.options({coeff:e}),this):i.options().coeff},gravity:function(e){return 1===arguments.length?(r.options({gravity:e}),this):r.options().gravity},theta:function(e){return 1===arguments.length?(r.options({theta:e}),this):r.options().theta},drag:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a="function"==typeof Object.create?Object.create(null):{},u=function(e){e&&(a[e.id]=i(e),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];n.node&&("add"===n.changeType?u(n.node):delete a[n.node.id])}};return e.addEventListener("changed",f),{run:function(){this.step()},step:function(){return s(),!0},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=!1,d=!0,l=0,h=0,v=!1,p=!1,m={x:0,y:0},g={offsetX:0,offsetY:0,scale:1},y=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},x=Viva.Graph.Utils.events(window),w=Viva.Graph.Utils.events({}).extend(),V=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},b=function(){return v=u.step()&&!p,V(),!v},N=function(e){return i?(h+=e,void 0):(e?(h+=e,i=Viva.Graph.Utils.timer(function(){return b()},n)):(l=0,h=0,i=Viva.Graph.Utils.timer(b,n)),void 0)},P=function(){v=!1,i.restart()},E=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},G=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);m.x=m.y=0,g.offsetX=t.width/2-(e.x2+e.x1)/2,g.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(g.offsetX,g.offsetY),d=!1},L=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},_=function(e){s.releaseNode(e)},A=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},I=function(e){s.releaseLink(e)},k=function(e){var t=!1;r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),p=!0,P()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/g.scale,r.y+n.y/g.scale),p=!0,V()},onStop:function(){u.pinNode(e,t),p=!1}})},T=function(e){r.bindDragNDrop(e,null)},C=function(){s.init(f),e.forEachNode(L),t.renderLinks&&e.forEachLink(A)},S=function(){s.release(f)},M=function(t){var n=t.node;"add"===t.changeType?(L(n),k(n),d&&G()):"remove"===t.changeType?(T(n),_(n),0===e.getNodesCount()&&(d=!0)):"update"===t.changeType&&(T(n),_(n),L(n),k(n))},U=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&A(n);else if("remove"===e.changeType)t.renderLinks&&I(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},D=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?M(n):n.link&&U(n);P()},R=function(){G(),b()},F=function(){a&&(a.release(),a=null)},O=function(){o&&(o.stop("changed",D),o=null)},z=function(e,t){if(!t){var n=Viva.Graph.Utils.getDimension(f);t={x:n.width/2,y:n.height/2}}var r=Math.pow(1.4,e?-.2:.2);g.scale=s.scale(r,t),V(),w.fire("scale",g.scale)},B=function(){x.on("resize",R),F(),a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){m.x+=t.x,m.y+=t.y,s.translateRel(t.x,t.y),V()}),a.onScroll(function(e,t,n){z(0>t,n)}),e.forEachNode(k),O(),o=Viva.Graph.Utils.events(e),o.on("changed",D)},Y=function(){c=!1,O(),F(),x.stop("resize",R),w.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&I(e)}),e.forEachNode(function(e){T(e),_(e)}),u.dispose(),S()};return{run:function(e){return c||(y(),E(),G(),C(),B(),c=!0),N(e),this},reset:function(){s.resetScale(),G(),g.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return V(),this},zoomOut:function(){z(!0)},zoomIn:function(){z(!1)},moveTo:function(e,t){s.graphCenterChanged(g.offsetX-e*g.scale,g.offsetY-t*g.scale),V()},getGraphics:function(){return s},dispose:function(){Y()},on:function(e,t){return w.addEventListener(e,t),this},off:function(e,t){return w.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"}; -var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},d=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},l=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?d(e):(d=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,l()},translateRel:function(e,r){t+=e,n+=r,l()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,l()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),d=f.attr("id"),l=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&d===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&l===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i,o=1,a={},u={},s=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},f=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},c=function(){return Viva.Graph.svg("line").attr("stroke","#999")},d=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},l=function(e){e.fire("rescaled")},h={x:0,y:0},v={x:0,y:0},p={x:0,y:0},m=function(){if(e){var t="matrix("+o+", 0, 0,"+o+","+n+","+r+")";e.attr("transform",t)}},g={getNodeUI:function(e){return a[e]},getLinkUI:function(e){return u[e]},node:function(e){return"function"==typeof e?(s=e,this):void 0},link:function(e){return"function"==typeof e?(c=e,this):void 0},placeNode:function(e){return f=e,this},placeLink:function(e){return d=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,m()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(i,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(i).translate(-u.x,-u.y),f=e.getCTM().multiply(s);o=f.a,n=f.e,r=f.f;var c="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",c),l(this),o},resetScale:function(){o=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),l(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),m(),"function"==typeof i&&i(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(t,n){var r=c(t);if(r)return r.position=n,r.link=t,u[t.id]=r,e.childElementCount>0?e.insertBefore(r,e.firstChild):e.appendChild(r),r},releaseLink:function(t){var n=u[t.id];n&&(e.removeChild(n),delete u[t.id])},addNode:function(t,n){var r=s(t);if(r)return r.position=n,r.node=t,a[t.id]=r,e.appendChild(r),r},releaseNode:function(t){var n=a[t.id];n&&(e.removeChild(n),delete a[t.id])},renderNodes:function(){for(var e in a)if(a.hasOwnProperty(e)){var t=a[e];h.x=t.position.x,h.y=t.position.y,f(t,h,t.node)}},renderLinks:function(){for(var e in u)if(u.hasOwnProperty(e)){var t=u[e];v.x=t.position.from.x,v.y=t.position.from.y,p.x=t.position.to.x,p.y=t.position.to.y,d(t,v,p,t.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):i=e),t},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(g).extend(),g},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,d=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(d.x)+" "+Math.round(d.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),l=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),v=new Float32Array(h),p=new Uint32Array(h),m=0,g=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(p),v=t,p=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(l,d),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;v[n*f]=t.x,v[n*f+1]=t.y,v[n*f+2]=e.size,p[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(p,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,d=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),v=0,p=new ArrayBuffer(16*d),m=new Float32Array(p),g=new Uint32Array(p),y=function(){if((v+1)*d>p.byteLength){var e=new ArrayBuffer(2*p.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,p=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,l),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),v+=1,o=e.id},removeLink:function(e){v>0&&(v-=1),v>e.id&&v>0&&r.copyArrayPart(g,e.id*c,v*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,p,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*v),o=v-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},d=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},l=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},v=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},p=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=l(e),o={offset:e};r.textureNumber>=s.length&&d();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=l(t.offset),r=l(o);p(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],v(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){v(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,d=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),l=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,v=0,p=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(l,d),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;p[n]=t.x-e.size,p[n+1]=t.y-e.size,p[n+2]=4*e._offset,p[n+3]=t.x+e.size,p[n+4]=t.y-e.size,p[n+5]=4*e._offset+1,p[n+6]=t.x-e.size,p[n+7]=t.y+e.size,p[n+8]=4*e._offset+2,p[n+9]=t.x-e.size,p[n+10]=t.y+e.size,p[n+11]=4*e._offset+2,p[n+12]=t.x+e.size,p[n+13]=t.y-e.size,p[n+14]=4*e._offset+1,p[n+15]=t.x+e.size,p[n+16]=t.y+e.size,p[n+17]=4*e._offset+3},createNode:function(t){p=i.extendArray(p,v,c),v+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){v>0&&(v-=1),v>t.id&&v>0&&(t.src&&e.remove(t.src),i.copyArrayPart(p,t.id*c,v*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,p,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*v)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f=0,c=0,d=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],l=[],h=[],v={},p={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(d),g.updateTransform(d)},V=function(){d=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},N=function(e){e.fire("rescaled")},P={getLinkUI:function(e){return p[e]},getNodeUI:function(e){return v[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return a=e,this},placeLink:function(e){return u=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){c>0&&m.render(),f>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(e,t){d[12]=2*e/i-1,d[13]=1-2*t/o,w()},addLink:function(e,t){var n=c++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,p[e.id]=r,r},addNode:function(e,t){var n=f++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),l[n]=r,v[e.id]=r,r},translateRel:function(e,t){d[12]+=2*d[0]*e/i/d[0],d[13]-=2*d[5]*t/o/d[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=d[12],r-=d[13],d[12]+=n*(1-e),d[13]+=r*(1-e),d[0]*=e,d[5]*=e,w(),N(this),d[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var f="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(f),f}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof s&&s(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){c>0&&(c-=1);var t=p[e.id];delete p[e.id],m.removeLink(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=h[c];h[n]=r,r.id=n}},releaseNode:function(e){f>0&&(f-=1);var t=v[e.id];delete v[e.id],g.removeNode(t);var n=t.id;if(f>n){if(0===f||f===n)return;var r=l[f];l[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;f>t;++t){var n=l[t];e.x=n.position.x,e.y=-n.position.y,a&&a(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;c>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,u&&u(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):s=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-d[12])/d[0],e.y=(e.y-d[13])/d[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;f>n;++n)if(t(l[n],e.x,e.y))return l[n].node;return null}};return Viva.Graph.Utils.events(P).extend(),P},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},i=function(t){return e.getNodeAtClientPos(t,r)},o=null,a=[],u=[],s=[],f=[],c=[],d=[],l=[],h=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},p=function(e){return v(e),!1},m=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(e){var r={x:0,y:0},g=null,y=+new Date,x=function(e){m(c,[g,e]),r.x=e.clientX,r.y=e.clientY},w=function(){h.stop("mousemove",x),h.stop("mouseup",w)},V=function(){n=e.getBoundingClientRect()};window.addEventListener("resize",V),V(),e.addEventListener("mousemove",function(e){if(!o){var t,s=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,t=i(r),t&&g!==t?(g=t,s=s||m(a,[g])):null===t&&g!==t&&(s=s||m(u,[g]),g=null),s&&v(e)}}),e.addEventListener("mousedown",function(e){var o,a=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]?(a=m(s,o),h.on("mousemove",x),h.on("mouseup",w),t=window.document.onselectstart,window.document.onselectstart=p,g=o[0]):g=null,a&&v(e)}),e.addEventListener("mouseup",function(e){var o,a=+new Date;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]&&(window.document.onselectstart=t,400>a-y&&o[0]===g?m(l,o):m(d,o),y=a,m(f,o)&&v(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&l.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file +var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.7",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},N=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},P=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",N,!1):e.addEventListener("DOMMouseScroll",N,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",N,!1):e.removeEventListener("DOMMouseScroll",N,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return P(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),P(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e="function"==typeof Object.create?Object.create(null):{},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e,t){var n=e.getNodesCount();return 0===n?0/0:t?e.getLinksCount()/(n*(n-1)):2*e.getLinksCount()/(n*(n-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,d=Math.sqrt(f*f+c*c);d>r&&(u.velocity.x=r*f/d,u.velocity.y=r*c/d),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};r="number"==typeof r?r:1;var o=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,r);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02,springTransform:function(){},timeStep:20,stableThreshold:.001});var n=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),r=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),i=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),o=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),a=new Viva.Graph.Rect,u=Viva.random("ted.com",103,114,101,97,116),s={},f=function(e){if(e.position)return e.position;var n=(a.x1+a.x2)/2,r=(a.y1+a.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],f=o.fromId!==e.id?s[o.fromId]:s[o.toId];f&&f.location&&(n=f.location.x,r=f.location.y)}return{x:n+u.next(i)-i/2,y:r+u.next(i)-i/2}},c=function(e){return s[e]},d=function(e){s[e]=null,delete s[e]},l={},h=function(t){var n=c(t);n.mass=1+e.getLinks(t).length/3},v=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},p=function(e){return e.isPinned},m=function(t){var r=c(t);if(!r){var i=e.getNode(t);if(!i)return;r=new Viva.Graph.Physics.Body,s[t]=r;var o=f(i);r.loc(o),h(t),v(i)&&(r.isPinned=!0),n.addBody(r)}},g=function(e){m(e.id)},y=function(t){var r=c(t.id);r&&(d(t.id),n.removeBody(r),0===e.getNodesCount()&&(a.x1=a.y1=0,a.x2=a.y2=0))},x=function(e){h(e.fromId),h(e.toId);var r=c(e.fromId),i=c(e.toId),o=n.addSpring(r,i,-1,e.weight);t.springTransform(e,o),l[e.id]=o},w=function(t){var r=l[t.id];if(r){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&h(i.id),o&&h(o.id),delete l[t.id],n.removeSpring(r)}},V=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&m(n.node.id),n.link&&x(n.link)):"remove"===n.changeType&&(n.node&&y(n.node),n.link&&w(n.link))}},b=function(){e.forEachNode(g),e.forEachLink(x),e.addEventListener("changed",V)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in s)if(s.hasOwnProperty(o)){var u=s[o];p(u)?(u.location.x=u.prevLocation.x,u.location.y=u.prevLocation.y):(u.prevLocation.x=u.location.x,u.prevLocation.y=u.location.y),t>u.location.x&&(t=u.location.x),u.location.x>r&&(r=u.location.x),n>u.location.y&&(n=u.location.y),u.location.y>i&&(i=u.location.y)}a.x1=t,a.x2=r,a.y1=n,a.y2=i}};return n.setSpringForce(i),n.setNbodyForce(r),n.setDragForce(o),b(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=n.run(t.timeStep);return N(),t.stableThreshold>e},isNodePinned:function(e){var t=c(e.id);return t?p(t):void 0},pinNode:function(e,t){var n=c(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=c(e);return t||(m(e),t=c(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=c(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return a},dispose:function(){e.removeEventListener("change",V)},springLength:function(e){return 1===arguments.length?(i.options({length:e}),this):i.options().length},springCoeff:function(e){return 1===arguments.length?(i.options({coeff:e}),this):i.options().coeff},gravity:function(e){return 1===arguments.length?(r.options({gravity:e}),this):r.options().gravity},theta:function(e){return 1===arguments.length?(r.options({theta:e}),this):r.options().theta},drag:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a="function"==typeof Object.create?Object.create(null):{},u=function(e){e&&(a[e.id]=i(e),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];n.node&&("add"===n.changeType?u(n.node):delete a[n.node.id])}};return e.addEventListener("changed",f),{run:function(){this.step()},step:function(){return s(),!0},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=void 0!==t.interactive?t.interactive:!0,d=!1,l=!0,h=0,v=0,p=!1,m=!1,g={x:0,y:0},y={offsetX:0,offsetY:0,scale:1},x=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},w=Viva.Graph.Utils.events(window),V=Viva.Graph.Utils.events({}).extend(),b=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},N=function(){return p=u.step()&&!m,b(),!p},P=function(e){return i?(v+=e,void 0):(e?(v+=e,i=Viva.Graph.Utils.timer(function(){return N()},n)):(h=0,v=0,i=Viva.Graph.Utils.timer(N,n)),void 0)},E=function(){p=!1,i.restart()},G=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},L=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);g.x=g.y=0,y.offsetX=t.width/2-(e.x2+e.x1)/2,y.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(y.offsetX,y.offsetY),l=!1},_=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},A=function(e){s.releaseNode(e)},I=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},k=function(e){s.releaseLink(e)},T=function(e){var t=!1,n="string"==typeof c&&-1!==c.indexOf("node")||c;n&&r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),m=!0,E()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/y.scale,r.y+n.y/y.scale),m=!0,b()},onStop:function(){u.pinNode(e,t),m=!1}})},C=function(e){r.bindDragNDrop(e,null)},S=function(){s.init(f),e.forEachNode(_),t.renderLinks&&e.forEachLink(I)},M=function(){s.release(f)},U=function(t){var n=t.node;"add"===t.changeType?(_(n),T(n),l&&L()):"remove"===t.changeType?(C(n),A(n),0===e.getNodesCount()&&(l=!0)):"update"===t.changeType&&(C(n),A(n),_(n),T(n))},D=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&I(n);else if("remove"===e.changeType)t.renderLinks&&k(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},R=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?U(n):n.link&&D(n);E()},O=function(){L(),N()},F=function(){a&&(a.release(),a=null)},z=function(){o&&(o.stop("changed",R),o=null)},B=function(e,t){if(!t){var n=Viva.Graph.Utils.getDimension(f);t={x:n.width/2,y:n.height/2}}var r=Math.pow(1.4,e?-.2:.2);y.scale=s.scale(r,t),b(),V.fire("scale",y.scale)},Y=function(){w.on("resize",O),F();var t="string"==typeof c&&-1!==c.indexOf("drag")||c;t&&(a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){g.x+=t.x,g.y+=t.y,s.translateRel(t.x,t.y),b()}));var n="string"==typeof c&&-1!==c.indexOf("scroll")||c;n&&a.onScroll(function(e,t,n){B(0>t,n)}),e.forEachNode(T),z(),o=Viva.Graph.Utils.events(e),o.on("changed",R)},X=function(){d=!1,z(),F(),w.stop("resize",O),V.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&k(e)}),e.forEachNode(function(e){C(e),A(e)}),u.dispose(),M()};return{run:function(e){return d||(x(),G(),L(),S(),Y(),d=!0),P(e),this},reset:function(){s.resetScale(),L(),y.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return b(),this},zoomOut:function(){B(!0)},zoomIn:function(){B(!1)},moveTo:function(e,t){s.graphCenterChanged(y.offsetX-e*y.scale,y.offsetY-t*y.scale),b()},getGraphics:function(){return s},dispose:function(){X()},on:function(e,t){return V.addEventListener(e,t),this},off:function(e,t){return V.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"}; +var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},d=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},l=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?d(e):(d=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,l()},translateRel:function(e,r){t+=e,n+=r,l()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,l()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),d=f.attr("id"),l=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&d===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&l===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i,o=1,a={},u={},s=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},f=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},c=function(){return Viva.Graph.svg("line").attr("stroke","#999")},d=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},l=function(e){e.fire("rescaled")},h={x:0,y:0},v={x:0,y:0},p={x:0,y:0},m=function(){if(e){var t="matrix("+o+", 0, 0,"+o+","+n+","+r+")";e.attr("transform",t)}},g={getNodeUI:function(e){return a[e]},getLinkUI:function(e){return u[e]},node:function(e){return"function"==typeof e?(s=e,this):void 0},link:function(e){return"function"==typeof e?(c=e,this):void 0},placeNode:function(e){return f=e,this},placeLink:function(e){return d=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,m()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(i,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(i).translate(-u.x,-u.y),f=e.getCTM().multiply(s);o=f.a,n=f.e,r=f.f;var c="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",c),l(this),o},resetScale:function(){o=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),l(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),m(),"function"==typeof i&&i(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(t,n){var r=c(t);if(r)return r.position=n,r.link=t,u[t.id]=r,e.childElementCount>0?e.insertBefore(r,e.firstChild):e.appendChild(r),r},releaseLink:function(t){var n=u[t.id];n&&(e.removeChild(n),delete u[t.id])},addNode:function(t,n){var r=s(t);if(r)return r.position=n,r.node=t,a[t.id]=r,e.appendChild(r),r},releaseNode:function(t){var n=a[t.id];n&&(e.removeChild(n),delete a[t.id])},renderNodes:function(){for(var e in a)if(a.hasOwnProperty(e)){var t=a[e];h.x=t.position.x,h.y=t.position.y,f(t,h,t.node)}},renderLinks:function(){for(var e in u)if(u.hasOwnProperty(e)){var t=u[e];v.x=t.position.from.x,v.y=t.position.from.y,p.x=t.position.to.x,p.y=t.position.to.y,d(t,v,p,t.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):i=e),t},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(g).extend(),g},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,d=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(d.x)+" "+Math.round(d.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),l=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),v=new Float32Array(h),p=new Uint32Array(h),m=0,g=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(p),v=t,p=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(l,d),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;v[n*f]=t.x,v[n*f+1]=t.y,v[n*f+2]=e.size,p[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(p,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,d=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),v=0,p=new ArrayBuffer(16*d),m=new Float32Array(p),g=new Uint32Array(p),y=function(){if((v+1)*d>p.byteLength){var e=new ArrayBuffer(2*p.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,p=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,l),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),v+=1,o=e.id},removeLink:function(e){v>0&&(v-=1),v>e.id&&v>0&&r.copyArrayPart(g,e.id*c,v*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,p,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*v),o=v-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},d=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},l=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},v=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},p=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=l(e),o={offset:e};r.textureNumber>=s.length&&d();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=l(t.offset),r=l(o);p(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],v(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){v(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,d=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),l=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,v=0,p=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(l,d),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;p[n]=t.x-e.size,p[n+1]=t.y-e.size,p[n+2]=4*e._offset,p[n+3]=t.x+e.size,p[n+4]=t.y-e.size,p[n+5]=4*e._offset+1,p[n+6]=t.x-e.size,p[n+7]=t.y+e.size,p[n+8]=4*e._offset+2,p[n+9]=t.x-e.size,p[n+10]=t.y+e.size,p[n+11]=4*e._offset+2,p[n+12]=t.x+e.size,p[n+13]=t.y-e.size,p[n+14]=4*e._offset+1,p[n+15]=t.x+e.size,p[n+16]=t.y+e.size,p[n+17]=4*e._offset+3},createNode:function(t){p=i.extendArray(p,v,c),v+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){v>0&&(v-=1),v>t.id&&v>0&&(t.src&&e.remove(t.src),i.copyArrayPart(p,t.id*c,v*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,p,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*v)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f=0,c=0,d=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],l=[],h=[],v={},p={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(d),g.updateTransform(d)},V=function(){d=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},N=function(e){e.fire("rescaled")},P={getLinkUI:function(e){return p[e]},getNodeUI:function(e){return v[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return a=e,this},placeLink:function(e){return u=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){c>0&&m.render(),f>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(e,t){d[12]=2*e/i-1,d[13]=1-2*t/o,w()},addLink:function(e,t){var n=c++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,p[e.id]=r,r},addNode:function(e,t){var n=f++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),l[n]=r,v[e.id]=r,r},translateRel:function(e,t){d[12]+=2*d[0]*e/i/d[0],d[13]-=2*d[5]*t/o/d[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=d[12],r-=d[13],d[12]+=n*(1-e),d[13]+=r*(1-e),d[0]*=e,d[5]*=e,w(),N(this),d[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var f="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(f),f}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof s&&s(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){c>0&&(c-=1);var t=p[e.id];delete p[e.id],m.removeLink(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=h[c];h[n]=r,r.id=n}},releaseNode:function(e){f>0&&(f-=1);var t=v[e.id];delete v[e.id],g.removeNode(t);var n=t.id;if(f>n){if(0===f||f===n)return;var r=l[f];l[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;f>t;++t){var n=l[t];e.x=n.position.x,e.y=-n.position.y,a&&a(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;c>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,u&&u(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):s=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-d[12])/d[0],e.y=(e.y-d[13])/d[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;f>n;++n)if(t(l[n],e.x,e.y))return l[n].node;return null}};return Viva.Graph.Utils.events(P).extend(),P},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},i=function(t){return e.getNodeAtClientPos(t,r)},o=null,a=[],u=[],s=[],f=[],c=[],d=[],l=[],h=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},p=function(e){return v(e),!1},m=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(e){var r={x:0,y:0},g=null,y=+new Date,x=function(e){m(c,[g,e]),r.x=e.clientX,r.y=e.clientY},w=function(){h.stop("mousemove",x),h.stop("mouseup",w)},V=function(){n=e.getBoundingClientRect()};window.addEventListener("resize",V),V(),e.addEventListener("mousemove",function(e){if(!o){var t,s=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,t=i(r),t&&g!==t?(g=t,s=s||m(a,[g])):null===t&&g!==t&&(s=s||m(u,[g]),g=null),s&&v(e)}}),e.addEventListener("mousedown",function(e){var o,a=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]?(a=m(s,o),h.on("mousemove",x),h.on("mouseup",w),t=window.document.onselectstart,window.document.onselectstart=p,g=o[0]):g=null,a&&v(e)}),e.addEventListener("mouseup",function(e){var o,a=+new Date;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]&&(window.document.onselectstart=t,400>a-y&&o[0]===g?m(l,o):m(d,o),y=a,m(f,o)&&v(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&l.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file diff --git a/src/Utils/events.js b/src/Utils/events.js index f8f3b40..3670775 100644 --- a/src/Utils/events.js +++ b/src/Utils/events.js @@ -146,4 +146,4 @@ Viva.Graph.Utils.events = function (element) { return eventuality(element); } }; -}; \ No newline at end of file +}; diff --git a/src/version.js b/src/version.js index 07fd4c2..de6a155 100644 --- a/src/version.js +++ b/src/version.js @@ -1 +1 @@ -Viva.Graph.version = '0.5.6'; +Viva.Graph.version = '0.5.7'; From 3caa4d06eb48ac898fd03e0179afebe1d96ca07e Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 20 Apr 2014 11:57:52 -0700 Subject: [PATCH 079/276] Just a small demo of adding graph inside graph By no means this is a guide how to do it. I'm just playing with SVG composition --- demos/other/graphInsideGraph.html | 168 ++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 demos/other/graphInsideGraph.html diff --git a/demos/other/graphInsideGraph.html b/demos/other/graphInsideGraph.html new file mode 100644 index 0000000..8859dc9 --- /dev/null +++ b/demos/other/graphInsideGraph.html @@ -0,0 +1,168 @@ + + + + + + + + + + + + + + From 4e18f9736334265a3a1a53da2f7b65b2471f6562 Mon Sep 17 00:00:00 2001 From: anvaka Date: Fri, 23 May 2014 23:08:05 -0700 Subject: [PATCH 080/276] Removed mixed quotes setting --- .jshintrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.jshintrc b/.jshintrc index b654edb..0ddb544 100644 --- a/.jshintrc +++ b/.jshintrc @@ -12,7 +12,7 @@ "latedef": true, "newcap": true, "noarg": true, - "quotmark": true, + "quotmark": false, "regexp": true, "undef": true, "unused": true, From f0ac041cf13e202d17e1fc85430145d3d7c846e2 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 7 Jun 2014 19:45:59 -0700 Subject: [PATCH 081/276] Naive positions precompute --- demos/other/precompute-naive.html | 57 +++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 demos/other/precompute-naive.html diff --git a/demos/other/precompute-naive.html b/demos/other/precompute-naive.html new file mode 100644 index 0000000..edebcfd --- /dev/null +++ b/demos/other/precompute-naive.html @@ -0,0 +1,57 @@ + + + + + VivaGraphs WebGL Precomupte - Naive + + + + + + + + + From 6d7dd7fe0048709a60b9208af5c8532ac7459698 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 7 Jun 2014 19:50:26 -0700 Subject: [PATCH 082/276] Added description --- demos/other/precompute-naive.html | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/demos/other/precompute-naive.html b/demos/other/precompute-naive.html index edebcfd..fc4a6ec 100644 --- a/demos/other/precompute-naive.html +++ b/demos/other/precompute-naive.html @@ -8,6 +8,10 @@ + + + + + +
+ + diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 11fd719..7219bf9 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -7,7 +7,7 @@ Viva.Graph = Viva.Graph || {}; if (typeof module !== 'undefined' && module.exports) { module.exports = Viva; } -Viva.Graph.version = '0.5.7'; +Viva.Graph.version = '0.5.71'; /** * Extends target object with given fields/values in the options object. * Unlike jQuery's extend this method does not override target object @@ -3044,6 +3044,8 @@ Viva.Graph.View.renderer = function (graph, settings) { renderGraph(); publicEvents.fire('scale', transform.scale); + + return transform.scale; }, listenToEvents = function () { @@ -3145,11 +3147,11 @@ Viva.Graph.View.renderer = function (graph, settings) { }, zoomOut: function () { - scale(true); + return scale(true); }, zoomIn: function () { - scale(false); + return scale(false); }, /** diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index abd94a0..82d2ea9 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.7",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},N=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},P=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",N,!1):e.addEventListener("DOMMouseScroll",N,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",N,!1):e.removeEventListener("DOMMouseScroll",N,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return P(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),P(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e="function"==typeof Object.create?Object.create(null):{},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e,t){var n=e.getNodesCount();return 0===n?0/0:t?e.getLinksCount()/(n*(n-1)):2*e.getLinksCount()/(n*(n-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,d=Math.sqrt(f*f+c*c);d>r&&(u.velocity.x=r*f/d,u.velocity.y=r*c/d),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};r="number"==typeof r?r:1;var o=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,r);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02,springTransform:function(){},timeStep:20,stableThreshold:.001});var n=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),r=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),i=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),o=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),a=new Viva.Graph.Rect,u=Viva.random("ted.com",103,114,101,97,116),s={},f=function(e){if(e.position)return e.position;var n=(a.x1+a.x2)/2,r=(a.y1+a.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],f=o.fromId!==e.id?s[o.fromId]:s[o.toId];f&&f.location&&(n=f.location.x,r=f.location.y)}return{x:n+u.next(i)-i/2,y:r+u.next(i)-i/2}},c=function(e){return s[e]},d=function(e){s[e]=null,delete s[e]},l={},h=function(t){var n=c(t);n.mass=1+e.getLinks(t).length/3},v=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},p=function(e){return e.isPinned},m=function(t){var r=c(t);if(!r){var i=e.getNode(t);if(!i)return;r=new Viva.Graph.Physics.Body,s[t]=r;var o=f(i);r.loc(o),h(t),v(i)&&(r.isPinned=!0),n.addBody(r)}},g=function(e){m(e.id)},y=function(t){var r=c(t.id);r&&(d(t.id),n.removeBody(r),0===e.getNodesCount()&&(a.x1=a.y1=0,a.x2=a.y2=0))},x=function(e){h(e.fromId),h(e.toId);var r=c(e.fromId),i=c(e.toId),o=n.addSpring(r,i,-1,e.weight);t.springTransform(e,o),l[e.id]=o},w=function(t){var r=l[t.id];if(r){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&h(i.id),o&&h(o.id),delete l[t.id],n.removeSpring(r)}},V=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&m(n.node.id),n.link&&x(n.link)):"remove"===n.changeType&&(n.node&&y(n.node),n.link&&w(n.link))}},b=function(){e.forEachNode(g),e.forEachLink(x),e.addEventListener("changed",V)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in s)if(s.hasOwnProperty(o)){var u=s[o];p(u)?(u.location.x=u.prevLocation.x,u.location.y=u.prevLocation.y):(u.prevLocation.x=u.location.x,u.prevLocation.y=u.location.y),t>u.location.x&&(t=u.location.x),u.location.x>r&&(r=u.location.x),n>u.location.y&&(n=u.location.y),u.location.y>i&&(i=u.location.y)}a.x1=t,a.x2=r,a.y1=n,a.y2=i}};return n.setSpringForce(i),n.setNbodyForce(r),n.setDragForce(o),b(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=n.run(t.timeStep);return N(),t.stableThreshold>e},isNodePinned:function(e){var t=c(e.id);return t?p(t):void 0},pinNode:function(e,t){var n=c(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=c(e);return t||(m(e),t=c(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=c(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return a},dispose:function(){e.removeEventListener("change",V)},springLength:function(e){return 1===arguments.length?(i.options({length:e}),this):i.options().length},springCoeff:function(e){return 1===arguments.length?(i.options({coeff:e}),this):i.options().coeff},gravity:function(e){return 1===arguments.length?(r.options({gravity:e}),this):r.options().gravity},theta:function(e){return 1===arguments.length?(r.options({theta:e}),this):r.options().theta},drag:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a="function"==typeof Object.create?Object.create(null):{},u=function(e){e&&(a[e.id]=i(e),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];n.node&&("add"===n.changeType?u(n.node):delete a[n.node.id])}};return e.addEventListener("changed",f),{run:function(){this.step()},step:function(){return s(),!0},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=void 0!==t.interactive?t.interactive:!0,d=!1,l=!0,h=0,v=0,p=!1,m=!1,g={x:0,y:0},y={offsetX:0,offsetY:0,scale:1},x=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},w=Viva.Graph.Utils.events(window),V=Viva.Graph.Utils.events({}).extend(),b=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},N=function(){return p=u.step()&&!m,b(),!p},P=function(e){return i?(v+=e,void 0):(e?(v+=e,i=Viva.Graph.Utils.timer(function(){return N()},n)):(h=0,v=0,i=Viva.Graph.Utils.timer(N,n)),void 0)},E=function(){p=!1,i.restart()},G=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},L=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);g.x=g.y=0,y.offsetX=t.width/2-(e.x2+e.x1)/2,y.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(y.offsetX,y.offsetY),l=!1},_=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},A=function(e){s.releaseNode(e)},I=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},k=function(e){s.releaseLink(e)},T=function(e){var t=!1,n="string"==typeof c&&-1!==c.indexOf("node")||c;n&&r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),m=!0,E()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/y.scale,r.y+n.y/y.scale),m=!0,b()},onStop:function(){u.pinNode(e,t),m=!1}})},C=function(e){r.bindDragNDrop(e,null)},S=function(){s.init(f),e.forEachNode(_),t.renderLinks&&e.forEachLink(I)},M=function(){s.release(f)},U=function(t){var n=t.node;"add"===t.changeType?(_(n),T(n),l&&L()):"remove"===t.changeType?(C(n),A(n),0===e.getNodesCount()&&(l=!0)):"update"===t.changeType&&(C(n),A(n),_(n),T(n))},D=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&I(n);else if("remove"===e.changeType)t.renderLinks&&k(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},R=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?U(n):n.link&&D(n);E()},O=function(){L(),N()},F=function(){a&&(a.release(),a=null)},z=function(){o&&(o.stop("changed",R),o=null)},B=function(e,t){if(!t){var n=Viva.Graph.Utils.getDimension(f);t={x:n.width/2,y:n.height/2}}var r=Math.pow(1.4,e?-.2:.2);y.scale=s.scale(r,t),b(),V.fire("scale",y.scale)},Y=function(){w.on("resize",O),F();var t="string"==typeof c&&-1!==c.indexOf("drag")||c;t&&(a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){g.x+=t.x,g.y+=t.y,s.translateRel(t.x,t.y),b()}));var n="string"==typeof c&&-1!==c.indexOf("scroll")||c;n&&a.onScroll(function(e,t,n){B(0>t,n)}),e.forEachNode(T),z(),o=Viva.Graph.Utils.events(e),o.on("changed",R)},X=function(){d=!1,z(),F(),w.stop("resize",O),V.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&k(e)}),e.forEachNode(function(e){C(e),A(e)}),u.dispose(),M()};return{run:function(e){return d||(x(),G(),L(),S(),Y(),d=!0),P(e),this},reset:function(){s.resetScale(),L(),y.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return b(),this},zoomOut:function(){B(!0)},zoomIn:function(){B(!1)},moveTo:function(e,t){s.graphCenterChanged(y.offsetX-e*y.scale,y.offsetY-t*y.scale),b()},getGraphics:function(){return s},dispose:function(){X()},on:function(e,t){return V.addEventListener(e,t),this},off:function(e,t){return V.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"}; +var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.71",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},N=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},P=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",N,!1):e.addEventListener("DOMMouseScroll",N,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",N,!1):e.removeEventListener("DOMMouseScroll",N,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return P(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),P(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e="function"==typeof Object.create?Object.create(null):{},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e,t){var n=e.getNodesCount();return 0===n?0/0:t?e.getLinksCount()/(n*(n-1)):2*e.getLinksCount()/(n*(n-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=e.bodies.length;for(n=0;a>n;++n){var u=e.bodies[n],s=t/u.mass;u.velocity.x+=s*u.force.x,u.velocity.y+=s*u.force.y;var f=u.velocity.x,c=u.velocity.y,d=Math.sqrt(f*f+c*c);d>r&&(u.velocity.x=r*f/d,u.velocity.y=r*c/d),i=t*u.velocity.x,o=t*u.velocity.y,u.location.x+=i,u.location.y+=o}return i*i+o*o}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};r="number"==typeof r?r:1;var o=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,r);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02,springTransform:function(){},timeStep:20,stableThreshold:.001});var n=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),r=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),i=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),o=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),a=new Viva.Graph.Rect,u=Viva.random("ted.com",103,114,101,97,116),s={},f=function(e){if(e.position)return e.position;var n=(a.x1+a.x2)/2,r=(a.y1+a.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],f=o.fromId!==e.id?s[o.fromId]:s[o.toId];f&&f.location&&(n=f.location.x,r=f.location.y)}return{x:n+u.next(i)-i/2,y:r+u.next(i)-i/2}},c=function(e){return s[e]},d=function(e){s[e]=null,delete s[e]},l={},h=function(t){var n=c(t);n.mass=1+e.getLinks(t).length/3},v=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},p=function(e){return e.isPinned},m=function(t){var r=c(t);if(!r){var i=e.getNode(t);if(!i)return;r=new Viva.Graph.Physics.Body,s[t]=r;var o=f(i);r.loc(o),h(t),v(i)&&(r.isPinned=!0),n.addBody(r)}},g=function(e){m(e.id)},y=function(t){var r=c(t.id);r&&(d(t.id),n.removeBody(r),0===e.getNodesCount()&&(a.x1=a.y1=0,a.x2=a.y2=0))},x=function(e){h(e.fromId),h(e.toId);var r=c(e.fromId),i=c(e.toId),o=n.addSpring(r,i,-1,e.weight);t.springTransform(e,o),l[e.id]=o},w=function(t){var r=l[t.id];if(r){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&h(i.id),o&&h(o.id),delete l[t.id],n.removeSpring(r)}},V=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&m(n.node.id),n.link&&x(n.link)):"remove"===n.changeType&&(n.node&&y(n.node),n.link&&w(n.link))}},b=function(){e.forEachNode(g),e.forEachLink(x),e.addEventListener("changed",V)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in s)if(s.hasOwnProperty(o)){var u=s[o];p(u)?(u.location.x=u.prevLocation.x,u.location.y=u.prevLocation.y):(u.prevLocation.x=u.location.x,u.prevLocation.y=u.location.y),t>u.location.x&&(t=u.location.x),u.location.x>r&&(r=u.location.x),n>u.location.y&&(n=u.location.y),u.location.y>i&&(i=u.location.y)}a.x1=t,a.x2=r,a.y1=n,a.y2=i}};return n.setSpringForce(i),n.setNbodyForce(r),n.setDragForce(o),b(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=n.run(t.timeStep);return N(),t.stableThreshold>e},isNodePinned:function(e){var t=c(e.id);return t?p(t):void 0},pinNode:function(e,t){var n=c(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=c(e);return t||(m(e),t=c(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=c(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return a},dispose:function(){e.removeEventListener("change",V)},springLength:function(e){return 1===arguments.length?(i.options({length:e}),this):i.options().length},springCoeff:function(e){return 1===arguments.length?(i.options({coeff:e}),this):i.options().coeff},gravity:function(e){return 1===arguments.length?(r.options({gravity:e}),this):r.options().gravity},theta:function(e){return 1===arguments.length?(r.options({theta:e}),this):r.options().theta},drag:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a="function"==typeof Object.create?Object.create(null):{},u=function(e){e&&(a[e.id]=i(e),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];n.node&&("add"===n.changeType?u(n.node):delete a[n.node.id])}};return e.addEventListener("changed",f),{run:function(){this.step()},step:function(){return s(),!0},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=void 0!==t.interactive?t.interactive:!0,d=!1,l=!0,h=0,v=0,p=!1,m=!1,g={x:0,y:0},y={offsetX:0,offsetY:0,scale:1},x=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},w=Viva.Graph.Utils.events(window),V=Viva.Graph.Utils.events({}).extend(),b=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},N=function(){return p=u.step()&&!m,b(),!p},P=function(e){return i?(v+=e,void 0):(e?(v+=e,i=Viva.Graph.Utils.timer(function(){return N()},n)):(h=0,v=0,i=Viva.Graph.Utils.timer(N,n)),void 0)},E=function(){p=!1,i.restart()},G=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},L=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);g.x=g.y=0,y.offsetX=t.width/2-(e.x2+e.x1)/2,y.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(y.offsetX,y.offsetY),l=!1},_=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},A=function(e){s.releaseNode(e)},I=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},k=function(e){s.releaseLink(e)},T=function(e){var t=!1,n="string"==typeof c&&-1!==c.indexOf("node")||c;n&&r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),m=!0,E()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/y.scale,r.y+n.y/y.scale),m=!0,b()},onStop:function(){u.pinNode(e,t),m=!1}})},C=function(e){r.bindDragNDrop(e,null)},S=function(){s.init(f),e.forEachNode(_),t.renderLinks&&e.forEachLink(I)},M=function(){s.release(f)},U=function(t){var n=t.node;"add"===t.changeType?(_(n),T(n),l&&L()):"remove"===t.changeType?(C(n),A(n),0===e.getNodesCount()&&(l=!0)):"update"===t.changeType&&(C(n),A(n),_(n),T(n))},D=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&I(n);else if("remove"===e.changeType)t.renderLinks&&k(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},R=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?U(n):n.link&&D(n);E()},O=function(){L(),N()},F=function(){a&&(a.release(),a=null)},z=function(){o&&(o.stop("changed",R),o=null)},B=function(e,t){if(!t){var n=Viva.Graph.Utils.getDimension(f);t={x:n.width/2,y:n.height/2}}var r=Math.pow(1.4,e?-.2:.2);return y.scale=s.scale(r,t),b(),V.fire("scale",y.scale),y.scale},Y=function(){w.on("resize",O),F();var t="string"==typeof c&&-1!==c.indexOf("drag")||c;t&&(a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){g.x+=t.x,g.y+=t.y,s.translateRel(t.x,t.y),b()}));var n="string"==typeof c&&-1!==c.indexOf("scroll")||c;n&&a.onScroll(function(e,t,n){B(0>t,n)}),e.forEachNode(T),z(),o=Viva.Graph.Utils.events(e),o.on("changed",R)},X=function(){d=!1,z(),F(),w.stop("resize",O),V.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&k(e)}),e.forEachNode(function(e){C(e),A(e)}),u.dispose(),M()};return{run:function(e){return d||(x(),G(),L(),S(),Y(),d=!0),P(e),this},reset:function(){s.resetScale(),L(),y.scale=1},pause:function(){i.stop()},resume:function(){i.restart()},rerender:function(){return b(),this},zoomOut:function(){return B(!0)},zoomIn:function(){return B(!1)},moveTo:function(e,t){s.graphCenterChanged(y.offsetX-e*y.scale,y.offsetY-t*y.scale),b()},getGraphics:function(){return s},dispose:function(){X()},on:function(e,t){return V.addEventListener(e,t),this},off:function(e,t){return V.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r);return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"}; var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},d=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},l=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?d(e):(d=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,l()},translateRel:function(e,r){t+=e,n+=r,l()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,l()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),d=f.attr("id"),l=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&d===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&l===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){var e,t,n,r,i,o=1,a={},u={},s=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},f=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},c=function(){return Viva.Graph.svg("line").attr("stroke","#999")},d=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},l=function(e){e.fire("rescaled")},h={x:0,y:0},v={x:0,y:0},p={x:0,y:0},m=function(){if(e){var t="matrix("+o+", 0, 0,"+o+","+n+","+r+")";e.attr("transform",t)}},g={getNodeUI:function(e){return a[e]},getLinkUI:function(e){return u[e]},node:function(e){return"function"==typeof e?(s=e,this):void 0},link:function(e){return"function"==typeof e?(c=e,this):void 0},placeNode:function(e){return f=e,this},placeLink:function(e){return d=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){n=e,r=t,m()},inputManager:Viva.Input.domInputManager,translateRel:function(n,r){var i=t.createSVGPoint(),o=e.getCTM(),a=t.createSVGPoint().matrixTransform(o.inverse());i.x=n,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";e.attr("transform",u)},scale:function(i,a){var u=t.createSVGPoint();u.x=a.x,u.y=a.y,u=u.matrixTransform(e.getCTM().inverse());var s=t.createSVGMatrix().translate(u.x,u.y).scale(i).translate(-u.x,-u.y),f=e.getCTM().multiply(s);o=f.a,n=f.e,r=f.f;var c="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return e.attr("transform",c),l(this),o},resetScale:function(){o=1;var t="matrix(1, 0, 0, 1, 0, 0)";return e.attr("transform",t),l(this),this},init:function(n){t=Viva.Graph.svg("svg"),e=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),t.appendChild(e),n.appendChild(t),m(),"function"==typeof i&&i(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(t,n){var r=c(t);if(r)return r.position=n,r.link=t,u[t.id]=r,e.childElementCount>0?e.insertBefore(r,e.firstChild):e.appendChild(r),r},releaseLink:function(t){var n=u[t.id];n&&(e.removeChild(n),delete u[t.id])},addNode:function(t,n){var r=s(t);if(r)return r.position=n,r.node=t,a[t.id]=r,e.appendChild(r),r},releaseNode:function(t){var n=a[t.id];n&&(e.removeChild(n),delete a[t.id])},renderNodes:function(){for(var e in a)if(a.hasOwnProperty(e)){var t=a[e];h.x=t.position.x,h.y=t.position.y,f(t,h,t.node)}},renderLinks:function(){for(var e in u)if(u.hasOwnProperty(e)){var t=u[e];v.x=t.position.from.x,v.y=t.position.from.y,p.x=t.position.to.x,p.y=t.position.to.y,d(t,v,p,t.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):i=e),t},getSvgRoot:function(){return t}};return Viva.Graph.Utils.events(g).extend(),g},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,d=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(d.x)+" "+Math.round(d.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),l=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),v=new Float32Array(h),p=new Uint32Array(h),m=0,g=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(p),v=t,p=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(l,d),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;v[n*f]=t.x,v[n*f+1]=t.y,v[n*f+2]=e.size,p[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(p,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,d=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),v=0,p=new ArrayBuffer(16*d),m=new Float32Array(p),g=new Uint32Array(p),y=function(){if((v+1)*d>p.byteLength){var e=new ArrayBuffer(2*p.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,p=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,l),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),v+=1,o=e.id},removeLink:function(e){v>0&&(v-=1),v>e.id&&v>0&&r.copyArrayPart(g,e.id*c,v*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,p,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*v),o=v-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},d=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},l=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},v=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},p=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=l(e),o={offset:e};r.textureNumber>=s.length&&d();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=l(t.offset),r=l(o);p(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],v(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){v(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,d=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),l=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,v=0,p=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(l,d),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;p[n]=t.x-e.size,p[n+1]=t.y-e.size,p[n+2]=4*e._offset,p[n+3]=t.x+e.size,p[n+4]=t.y-e.size,p[n+5]=4*e._offset+1,p[n+6]=t.x-e.size,p[n+7]=t.y+e.size,p[n+8]=4*e._offset+2,p[n+9]=t.x-e.size,p[n+10]=t.y+e.size,p[n+11]=4*e._offset+2,p[n+12]=t.x+e.size,p[n+13]=t.y-e.size,p[n+14]=4*e._offset+1,p[n+15]=t.x+e.size,p[n+16]=t.y+e.size,p[n+17]=4*e._offset+3},createNode:function(t){p=i.extendArray(p,v,c),v+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){v>0&&(v-=1),v>t.id&&v>0&&(t.src&&e.remove(t.src),i.copyArrayPart(p,t.id*c,v*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,p,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*v)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f=0,c=0,d=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],l=[],h=[],v={},p={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(d),g.updateTransform(d)},V=function(){d=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},N=function(e){e.fire("rescaled")},P={getLinkUI:function(e){return p[e]},getNodeUI:function(e){return v[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return a=e,this},placeLink:function(e){return u=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){c>0&&m.render(),f>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(e,t){d[12]=2*e/i-1,d[13]=1-2*t/o,w()},addLink:function(e,t){var n=c++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,p[e.id]=r,r},addNode:function(e,t){var n=f++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),l[n]=r,v[e.id]=r,r},translateRel:function(e,t){d[12]+=2*d[0]*e/i/d[0],d[13]-=2*d[5]*t/o/d[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=d[12],r-=d[13],d[12]+=n*(1-e),d[13]+=r*(1-e),d[0]*=e,d[5]*=e,w(),N(this),d[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,n=window.document.createElement("canvas"),b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var f="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(f),f}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof s&&s(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){c>0&&(c-=1);var t=p[e.id];delete p[e.id],m.removeLink(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=h[c];h[n]=r,r.id=n}},releaseNode:function(e){f>0&&(f-=1);var t=v[e.id];delete v[e.id],g.removeNode(t);var n=t.id;if(f>n){if(0===f||f===n)return;var r=l[f];l[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;f>t;++t){var n=l[t];e.x=n.position.x,e.y=-n.position.y,a&&a(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;c>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,u&&u(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):s=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-d[12])/d[0],e.y=(e.y-d[13])/d[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;f>n;++n)if(t(l[n],e.x,e.y))return l[n].node;return null}};return Viva.Graph.Utils.events(P).extend(),P},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},i=function(t){return e.getNodeAtClientPos(t,r)},o=null,a=[],u=[],s=[],f=[],c=[],d=[],l=[],h=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},p=function(e){return v(e),!1},m=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(e){var r={x:0,y:0},g=null,y=+new Date,x=function(e){m(c,[g,e]),r.x=e.clientX,r.y=e.clientY},w=function(){h.stop("mousemove",x),h.stop("mouseup",w)},V=function(){n=e.getBoundingClientRect()};window.addEventListener("resize",V),V(),e.addEventListener("mousemove",function(e){if(!o){var t,s=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,t=i(r),t&&g!==t?(g=t,s=s||m(a,[g])):null===t&&g!==t&&(s=s||m(u,[g]),g=null),s&&v(e)}}),e.addEventListener("mousedown",function(e){var o,a=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]?(a=m(s,o),h.on("mousemove",x),h.on("mouseup",w),t=window.document.onselectstart,window.document.onselectstart=p,g=o[0]):g=null,a&&v(e)}),e.addEventListener("mouseup",function(e){var o,a=+new Date;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]&&(window.document.onselectstart=t,400>a-y&&o[0]===g?m(l,o):m(d,o),y=a,m(f,o)&&v(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&l.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file diff --git a/src/View/renderer.js b/src/View/renderer.js index 908da75..0a15c31 100644 --- a/src/View/renderer.js +++ b/src/View/renderer.js @@ -307,6 +307,8 @@ Viva.Graph.View.renderer = function (graph, settings) { renderGraph(); publicEvents.fire('scale', transform.scale); + + return transform.scale; }, listenToEvents = function () { @@ -408,11 +410,11 @@ Viva.Graph.View.renderer = function (graph, settings) { }, zoomOut: function () { - scale(true); + return scale(true); }, zoomIn: function () { - scale(false); + return scale(false); }, /** diff --git a/src/version.js b/src/version.js index de6a155..cbb256e 100644 --- a/src/version.js +++ b/src/version.js @@ -1 +1 @@ -Viva.Graph.version = '0.5.7'; +Viva.Graph.version = '0.5.71'; From a5c5c92cdecd6964b0bb0c1cb0aaa63c30ffc9e4 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 7 Jun 2014 20:33:45 -0700 Subject: [PATCH 084/276] Removed unused function, updated title --- demos/other/precompute-advanced.html | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/demos/other/precompute-advanced.html b/demos/other/precompute-advanced.html index 675863a..49892e7 100644 --- a/demos/other/precompute-advanced.html +++ b/demos/other/precompute-advanced.html @@ -2,7 +2,7 @@ - VivaGraphs WebGL Precomupte - Naive + VivaGraphs WebGL Precomupte - Advanced -
+
Zoom In | Zoom Out
Reset
From fdcaf7dbb8c21e11dbde37f29d9d07191fe39b70 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 28 Sep 2014 17:18:34 -0700 Subject: [PATCH 091/276] Leting late function declaration --- .jshintrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.jshintrc b/.jshintrc index 0ddb544..c59ae7c 100644 --- a/.jshintrc +++ b/.jshintrc @@ -9,7 +9,7 @@ "eqeqeq": true, "immed": true, "indent": 4, - "latedef": true, + "latedef": false, "newcap": true, "noarg": true, "quotmark": false, From 6e1d12ab4feacd4aaf39fa08a873680ec99d3205 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 28 Sep 2014 17:24:58 -0700 Subject: [PATCH 092/276] Changed stable threshold check Now it uses absolute value. Hopefully this will help to avoid bugs like https://github.com/anvaka/VivaGraphJS/issues/100#issuecomment-55568513 --- src/Layout/forceDirected.js | 2 +- src/Physics/eulerIntegrator.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Layout/forceDirected.js b/src/Layout/forceDirected.js index a52ff2d..a03ab98 100644 --- a/src/Layout/forceDirected.js +++ b/src/Layout/forceDirected.js @@ -79,7 +79,7 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { /** * Maximum movement of the system which can be considered as stabilized */ - stableThreshold: 0.001 + stableThreshold: 0.009 }); var forceSimulator = Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()), diff --git a/src/Physics/eulerIntegrator.js b/src/Physics/eulerIntegrator.js index 6b375cd..fc23cb5 100644 --- a/src/Physics/eulerIntegrator.js +++ b/src/Physics/eulerIntegrator.js @@ -41,11 +41,11 @@ Viva.Graph.Physics.eulerIntegrator = function () { body.location.x += dx; body.location.y += dy; - tx += dx; - ty += dy; + tx += Math.abs(dx); + ty += Math.abs(dy); } - return (tx * tx + ty * ty)/max; + return (tx + ty)/max; } }; }; From 3b40519819145ea8d9a81576b2afc4275f8f35fa Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 28 Sep 2014 17:25:20 -0700 Subject: [PATCH 093/276] Added early container initialization --- CHANGELOG | 10 + .../tutorial_svg/05 - Edges With Arrows.html | 16 +- dist/vivagraph.js | 9098 +++++++++-------- dist/vivagraph.min.js | 4 +- src/View/svgGraphics.js | 19 +- src/View/webglGraphics.js | 9 +- src/version.js | 2 +- 7 files changed, 4589 insertions(+), 4569 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index ab0c1ad..4d627dd 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,13 @@ +v0.5.8 + date: Sep 28, 2014 + - Graphics object no longer waits `init` method to create container. Fixes + https://github.com/anvaka/VivaGraphJS/issues/82 + - When renderer is paused clicking on any node will not reset it. Fixes + https://github.com/anvaka/VivaGraphJS/issues/98 + - Calculating stable threshold based on absolute value. Fixes + https://github.com/anvaka/VivaGraphJS/issues/100#issuecomment-55568513 + - Minor code style improvements + v0.5.6 date: Apr 05, 2014 - Using Object.create where possible to avoid node id collision with diff --git a/demos/tutorial_svg/05 - Edges With Arrows.html b/demos/tutorial_svg/05 - Edges With Arrows.html index 35253fd..d9cc622 100644 --- a/demos/tutorial_svg/05 - Edges With Arrows.html +++ b/demos/tutorial_svg/05 - Edges With Arrows.html @@ -15,12 +15,6 @@ var graphics = Viva.Graph.View.svgGraphics(), nodeSize = 24; - // In this example we fire off renderer before anything is added to - // the graph: - var renderer = Viva.Graph.View.renderer(graph, { - graphics : graphics - }); - renderer.run(); graphics.node(function(node) { return Viva.Graph.svg('image') @@ -104,11 +98,11 @@ graph.addNode('indexzero', 'd43e8ea63b61e7669ded5b9d3c2e980f'); graph.addLink('anvaka', 'indexzero'); - // You might have noticed that the order in which - // we call renderer.run() and graph.addNode()/addLink() differs from - // previous tutorials. The reason for this is that graphics.getSVGRoot() returns - // null if it was not initialized by the renderer yet. Maybe this behavior will - // be fixed in future. + // All is ready. Render the graph: + var renderer = Viva.Graph.View.renderer(graph, { + graphics : graphics + }); + renderer.run(); } diff --git a/dist/vivagraph.js b/dist/vivagraph.js index d71b28b..b566dff 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -7,129 +7,129 @@ Viva.Graph = Viva.Graph || {}; if (typeof module !== 'undefined' && module.exports) { module.exports = Viva; } -Viva.Graph.version = '0.5.72'; -/** - * Extends target object with given fields/values in the options object. - * Unlike jQuery's extend this method does not override target object - * properties if their type matches corresponding type in the options object - */ -Viva.lazyExtend = function (target, options) { - var key; - if (!target) { target = {}; } - if (options) { - for (key in options) { - if (options.hasOwnProperty(key)) { - var targetHasIt = target.hasOwnProperty(key), - optionsValueType = typeof options[key], - shouldReplace = !targetHasIt || (typeof target[key] !== optionsValueType); - - if (shouldReplace) { - target[key] = options[key]; - } else if (optionsValueType === 'object') { - // go deep, don't care about loops here, we are simple API!: - target[key] = Viva.lazyExtend(target[key], options[key]); - } - } - } - } - - return target; -}; -/** - * Implenetation of seeded pseudo random number generator, based on Robert Jenkin's 32 bit integer hash function - * - * Usage example: - * var random = Viva.random(seedNumber), - * i = random.next(100); // returns random number from [0 .. 100) range. - */ - -Viva.random = function () { - var firstArg = arguments[0]; - var seed; - if (typeof firstArg === 'number') { - seed = firstArg; - } else if (typeof firstArg === 'string') { - seed = firstArg.length; - } else { - seed = +new Date(); - } - var randomFunc = function() { - // Robert Jenkins' 32 bit integer hash function. - seed = ((seed + 0x7ed55d16) + (seed << 12)) & 0xffffffff; - seed = ((seed ^ 0xc761c23c) ^ (seed >>> 19)) & 0xffffffff; - seed = ((seed + 0x165667b1) + (seed << 5)) & 0xffffffff; - seed = ((seed + 0xd3a2646c) ^ (seed << 9)) & 0xffffffff; - seed = ((seed + 0xfd7046c5) + (seed << 3)) & 0xffffffff; - seed = ((seed ^ 0xb55a4f09) ^ (seed >>> 16)) & 0xffffffff; - return (seed & 0xfffffff) / 0x10000000; - }; - - return { - /** - * Generates random integer number in the range from 0 (inclusive) to maxValue (exclusive) - * - * @param maxValue is REQUIRED. Ommitit this numbe will result in NaN values from PRNG. - */ - next : function (maxValue) { - return Math.floor(randomFunc() * maxValue); - }, - - /** - * Generates random double number in the range from 0 (inclusive) to 1 (exclusive) - * This function is the same as Math.random() (except that it could be seeded) - */ - nextDouble : function () { - return randomFunc(); - } - }; -}; - -/** - * Iterates over array in arbitrary order. The iterator modifies actual array content. - * It's based on modern version of Fisher–Yates shuffle algorithm. - * - * @see http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm - * - * @param array to be shuffled - * @param random - a [seeded] random number generator to produce same sequences. This parameter - * is optional. If you don't need determenistic randomness keep it blank. - */ -Viva.randomIterator = function (array, random) { - random = random || Viva.random(); - - return { - forEach : function (callback) { - var i, j, t; - for (i = array.length - 1; i > 0; --i) { - j = random.next(i + 1); // i inclusive - t = array[j]; - array[j] = array[i]; - array[i] = t; - - callback(t); - } - - if (array.length) { - callback(array[0]); - } - }, - - /** - * Shuffles array randomly. - */ - shuffle : function () { - var i, j, t; - for (i = array.length - 1; i > 0; --i) { - j = random.next(i + 1); // i inclusive - t = array[j]; - array[j] = array[i]; - array[i] = t; - } - - return array; - } - }; -}; +Viva.Graph.version = '0.5.8'; +/** + * Extends target object with given fields/values in the options object. + * Unlike jQuery's extend this method does not override target object + * properties if their type matches corresponding type in the options object + */ +Viva.lazyExtend = function (target, options) { + var key; + if (!target) { target = {}; } + if (options) { + for (key in options) { + if (options.hasOwnProperty(key)) { + var targetHasIt = target.hasOwnProperty(key), + optionsValueType = typeof options[key], + shouldReplace = !targetHasIt || (typeof target[key] !== optionsValueType); + + if (shouldReplace) { + target[key] = options[key]; + } else if (optionsValueType === 'object') { + // go deep, don't care about loops here, we are simple API!: + target[key] = Viva.lazyExtend(target[key], options[key]); + } + } + } + } + + return target; +}; +/** + * Implenetation of seeded pseudo random number generator, based on Robert Jenkin's 32 bit integer hash function + * + * Usage example: + * var random = Viva.random(seedNumber), + * i = random.next(100); // returns random number from [0 .. 100) range. + */ + +Viva.random = function () { + var firstArg = arguments[0]; + var seed; + if (typeof firstArg === 'number') { + seed = firstArg; + } else if (typeof firstArg === 'string') { + seed = firstArg.length; + } else { + seed = +new Date(); + } + var randomFunc = function() { + // Robert Jenkins' 32 bit integer hash function. + seed = ((seed + 0x7ed55d16) + (seed << 12)) & 0xffffffff; + seed = ((seed ^ 0xc761c23c) ^ (seed >>> 19)) & 0xffffffff; + seed = ((seed + 0x165667b1) + (seed << 5)) & 0xffffffff; + seed = ((seed + 0xd3a2646c) ^ (seed << 9)) & 0xffffffff; + seed = ((seed + 0xfd7046c5) + (seed << 3)) & 0xffffffff; + seed = ((seed ^ 0xb55a4f09) ^ (seed >>> 16)) & 0xffffffff; + return (seed & 0xfffffff) / 0x10000000; + }; + + return { + /** + * Generates random integer number in the range from 0 (inclusive) to maxValue (exclusive) + * + * @param maxValue is REQUIRED. Ommitit this numbe will result in NaN values from PRNG. + */ + next : function (maxValue) { + return Math.floor(randomFunc() * maxValue); + }, + + /** + * Generates random double number in the range from 0 (inclusive) to 1 (exclusive) + * This function is the same as Math.random() (except that it could be seeded) + */ + nextDouble : function () { + return randomFunc(); + } + }; +}; + +/** + * Iterates over array in arbitrary order. The iterator modifies actual array content. + * It's based on modern version of Fisher–Yates shuffle algorithm. + * + * @see http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm + * + * @param array to be shuffled + * @param random - a [seeded] random number generator to produce same sequences. This parameter + * is optional. If you don't need determenistic randomness keep it blank. + */ +Viva.randomIterator = function (array, random) { + random = random || Viva.random(); + + return { + forEach : function (callback) { + var i, j, t; + for (i = array.length - 1; i > 0; --i) { + j = random.next(i + 1); // i inclusive + t = array[j]; + array[j] = array[i]; + array[i] = t; + + callback(t); + } + + if (array.length) { + callback(array[0]); + } + }, + + /** + * Shuffles array randomly. + */ + shuffle : function () { + var i, j, t; + for (i = array.length - 1; i > 0; --i) { + j = random.next(i + 1); // i inclusive + t = array[j]; + array[j] = array[i]; + array[i] = t; + } + + return array; + } + }; +}; Viva.BrowserInfo = (function () { if (typeof window === "undefined" || !window.hasOwnProperty("navigator")) { return { @@ -155,28 +155,28 @@ Viva.BrowserInfo = (function () { version: match[2] || "0" }; }()); -/** - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com - */ - -Viva.Graph.Utils = Viva.Graph.Utils || {}; - -Viva.Graph.Utils.indexOfElementInArray = function (element, array) { - if (array.indexOf) { - return array.indexOf(element); - } - - var len = array.length, - i; - - for (i = 0; i < len; i += 1) { - if (array.hasOwnProperty(i) && (array[i] === element)) { - return i; - } - } - - return -1; -}; +/** + * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + */ + +Viva.Graph.Utils = Viva.Graph.Utils || {}; + +Viva.Graph.Utils.indexOfElementInArray = function (element, array) { + if (array.indexOf) { + return array.indexOf(element); + } + + var len = array.length, + i; + + for (i = 0; i < len; i += 1) { + if (array.hasOwnProperty(i) && (array[i] === element)) { + return i; + } + } + + return -1; +}; Viva.Graph.Utils = Viva.Graph.Utils || {}; Viva.Graph.Utils.getDimension = function (container) { @@ -212,476 +212,476 @@ Viva.Graph.Utils.findElementPosition = function (obj) { } return [curleft, curtop]; -};/** - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com - */ - -Viva.Graph.Utils = Viva.Graph.Utils || {}; - -// TODO: I don't really like the way I implemented events. It looks clumsy and -// hard to understand. Refactor it. - -// TODO: This is really painful. Please don't use this class anymore, I will -// definitely depricate it or update its interface. - -/** - * Allows to start/stop listen to element's events. An element can be arbitrary - * DOM element, or object with eventuality behavior. - * - * To add eventuality behavior to arbitrary object 'obj' call - * Viva.Graph.Utils.event(obj).extend() method. - * After this call is made the object can use obj.fire(eventName, params) method, and listeners - * can listen to event by Viva.Graph.Utils.events(obj).on(eventName, callback) method. - */ -Viva.Graph.Utils.events = function (element) { - - /** - * Extends arbitrary object with fire method and allows it to be used with on/stop methods. - * - * This behavior is based on Crockford's eventuality example, but with a minor changes: - * - fire() method accepts parameters to pass to callbacks (instead of setting them in 'on' method) - * - on() method is replaced with addEventListener(), to let objects be used as a DOM objects. - * - behavoir contract is simplified to "string as event name"/"function as callback" convention. - * - removeEventListener() method added to let unsubscribe from events. - */ - var eventuality = function (that) { - var registry = {}; - - /** - * Fire an event on an object. The event is a string containing the name of the event - * Handlers registered by the 'addEventListener' method that match the event name - * will be invoked. - */ - that.fire = function (eventName, parameters) { - var registeredHandlers, - callback, - handler, - i; - - if (typeof eventName !== "string") { - throw "Only strings can be used as even type"; - } - - // If an array of handlers exist for this event, then - // loop through it and execute the handlers in order. - if (registry.hasOwnProperty(eventName)) { - registeredHandlers = registry[eventName]; - for (i = 0; i < registeredHandlers.length; ++i) { - handler = registeredHandlers[i]; - callback = handler.method; - callback(parameters); - } - } - - return this; - }; - - that.addEventListener = function (eventName, callback) { - if (typeof callback !== "function") { - throw "Only functions allowed to be callbacks"; - } - - var handler = { - method: callback - }; - if (registry.hasOwnProperty(eventName)) { - registry[eventName].push(handler); - } else { - registry[eventName] = [handler]; - } - - return this; - }; - - that.removeEventListener = function (eventName, callback) { - if (typeof callback !== "function") { - throw "Only functions allowed to be callbacks"; - } - - if (registry.hasOwnProperty(eventName)) { - var handlers = registry[eventName], - i; - - for (i = 0; i < handlers.length; ++i) { - if (handlers[i].callback === callback) { - handlers.splice(i); - break; - } - } - } - - return this; - }; - - that.removeAllListeners = function () { - var eventName; - for (eventName in registry) { - if (registry.hasOwnProperty(eventName)) { - delete registry[eventName]; - } - } - }; - - return that; - }; - - return { - /** - * Registes callback to be called when element fires event with given event name. - */ - on : function (eventName, callback) { - if (element.addEventListener) {// W3C DOM and eventuality objecets. - element.addEventListener(eventName, callback, false); - } else if (element.attachEvent) { // IE DOM - element.attachEvent("on" + eventName, callback); - } - - return this; - }, - - /** - * Unsubcribes from object's events. - */ - stop : function (eventName, callback) { - if (element.removeEventListener) { - element.removeEventListener(eventName, callback, false); - } else if (element.detachEvent) { - element.detachEvent("on" + eventName, callback); - } - }, - - /** - * Adds eventuality to arbitrary JavaScript object. Eventuality adds - * fire(), addEventListner() and removeEventListners() to the target object. - * - * This is required if you want to use object with on(), stop() methods. - */ - extend : function () { - return eventuality(element); - } - }; -}; -/** - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com - */ - -Viva.Graph.Utils = Viva.Graph.Utils || {}; - -// TODO: Move to input namespace -// TODO: Methods should be extracted into the prototype. This class -// does not need to consume so much memory for every tracked element -Viva.Graph.Utils.dragndrop = function (element) { - var start, - drag, - end, - scroll, - prevSelectStart, - prevDragStart, - documentEvents = Viva.Graph.Utils.events(window.document), - elementEvents = Viva.Graph.Utils.events(element), - findElementPosition = Viva.Graph.Utils.findElementPosition, - - startX = 0, - startY = 0, - dragObject, - touchInProgress = false, - pinchZoomLength = 0, - - getMousePos = function (e) { - var posx = 0, - posy = 0; - - e = e || window.event; - - if (e.pageX || e.pageY) { - posx = e.pageX; - posy = e.pageY; - } else if (e.clientX || e.clientY) { - posx = e.clientX + window.document.body.scrollLeft + window.document.documentElement.scrollLeft; - posy = e.clientY + window.document.body.scrollTop + window.document.documentElement.scrollTop; - } - - return [posx, posy]; - }, - - move = function (e, clientX, clientY) { - if (drag) { - drag(e, {x : clientX - startX, y : clientY - startY }); - } - - startX = clientX; - startY = clientY; - }, - - stopPropagation = function (e) { - if (e.stopPropagation) { e.stopPropagation(); } else { e.cancelBubble = true; } - }, - preventDefault = function (e) { - if (e.preventDefault) { e.preventDefault(); } - }, - - handleDisabledEvent = function (e) { - stopPropagation(e); - return false; - }, - - handleMouseMove = function (e) { - e = e || window.event; - - move(e, e.clientX, e.clientY); - }, - - handleMouseDown = function (e) { - e = e || window.event; - if (touchInProgress) { - // modern browsers will fire mousedown for touch events too - // we do not want this, since touch is handled separately. - stopPropagation(e); - return false; - } - // for IE, left click == 1 - // for Firefox, left click == 0 - var isLeftButton = ((e.button === 1 && window.event !== null) || e.button === 0); - - if (isLeftButton) { - startX = e.clientX; - startY = e.clientY; - - // TODO: bump zIndex? - dragObject = e.target || e.srcElement; - - if (start) { start(e, {x: startX, y : startY}); } - - documentEvents.on('mousemove', handleMouseMove); - documentEvents.on('mouseup', handleMouseUp); - - - stopPropagation(e); - // TODO: What if event already there? Not bullet proof: - prevSelectStart = window.document.onselectstart; - prevDragStart = window.document.ondragstart; - - window.document.onselectstart = handleDisabledEvent; - dragObject.ondragstart = handleDisabledEvent; - - // prevent text selection (except IE) - return false; - } - }, - - handleMouseUp = function (e) { - e = e || window.event; - - documentEvents.stop('mousemove', handleMouseMove); - documentEvents.stop('mouseup', handleMouseUp); - - window.document.onselectstart = prevSelectStart; - dragObject.ondragstart = prevDragStart; - dragObject = null; - if (end) { end(e); } - }, - - handleMouseWheel = function (e) { - if (typeof scroll !== 'function') { - return; - } - - e = e || window.event; - if (e.preventDefault) { - e.preventDefault(); - } - - e.returnValue = false; - var delta, - mousePos = getMousePos(e), - elementOffset = findElementPosition(element), - relMousePos = { - x: mousePos[0] - elementOffset[0], - y: mousePos[1] - elementOffset[1] - }; - - if (e.wheelDelta) { - delta = e.wheelDelta / 360; // Chrome/Safari - } else { - delta = e.detail / -9; // Mozilla - } - - scroll(e, delta, relMousePos); - }, - - updateScrollEvents = function (scrollCallback) { - if (!scroll && scrollCallback) { - // client is interested in scrolling. Start listening to events: - if (Viva.BrowserInfo.browser === 'webkit') { - element.addEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari - } else { - element.addEventListener('DOMMouseScroll', handleMouseWheel, false); // Others - } - } else if (scroll && !scrollCallback) { - if (Viva.BrowserInfo.browser === 'webkit') { - element.removeEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari - } else { - element.removeEventListener('DOMMouseScroll', handleMouseWheel, false); // Others - } - } - - scroll = scrollCallback; - }, - - getPinchZoomLength = function(finger1, finger2) { - return (finger1.clientX - finger2.clientX) * (finger1.clientX - finger2.clientX) + - (finger1.clientY - finger2.clientY) * (finger1.clientY - finger2.clientY); - }, - - handleTouchMove = function (e) { - if (e.touches.length === 1) { - stopPropagation(e); - - var touch = e.touches[0]; - move(e, touch.clientX, touch.clientY); - } else if (e.touches.length === 2) { - // it's a zoom: - var currentPinchLength = getPinchZoomLength(e.touches[0], e.touches[1]); - var delta = 0; - if (currentPinchLength < pinchZoomLength) { - delta = -1; - } else if (currentPinchLength > pinchZoomLength) { - delta = 1; - } - scroll(e, delta, {x: e.touches[0].clientX, y: e.touches[0].clientY}); - pinchZoomLength = currentPinchLength; - stopPropagation(e); - preventDefault(e); - } - }, - - handleTouchEnd = function (e) { - touchInProgress = false; - documentEvents.stop('touchmove', handleTouchMove); - documentEvents.stop('touchend', handleTouchEnd); - documentEvents.stop('touchcancel', handleTouchEnd); - dragObject = null; - if (end) { end(e); } - }, - - handleSignleFingerTouch = function (e, touch) { - stopPropagation(e); - preventDefault(e); - - startX = touch.clientX; - startY = touch.clientY; - - dragObject = e.target || e.srcElement; - - if (start) { start(e, {x: startX, y : startY}); } - // TODO: can I enter into the state when touch is in progress - // but it's still a single finger touch? - if (!touchInProgress) { - touchInProgress = true; - documentEvents.on('touchmove', handleTouchMove); - documentEvents.on('touchend', handleTouchEnd); - documentEvents.on('touchcancel', handleTouchEnd); - } - }, - - handleTouchStart = function (e) { - console.log('Touch start for ', element); - if (e.touches.length === 1) { - return handleSignleFingerTouch(e, e.touches[0]); - } else if (e.touches.length === 2) { - // handleTouchMove() will care about pinch zoom. - stopPropagation(e); - preventDefault(e); - - pinchZoomLength = getPinchZoomLength(e.touches[0], e.touches[1]); - - } - // don't care about the rest. - }; - - - elementEvents.on('mousedown', handleMouseDown); - elementEvents.on('touchstart', handleTouchStart); - - return { - onStart : function (callback) { - start = callback; - return this; - }, - - onDrag : function (callback) { - drag = callback; - return this; - }, - - onStop : function (callback) { - end = callback; - return this; - }, - - /** - * Occurs when mouse wheel event happens. callback = function(e, scrollDelta, scrollPoint); - */ - onScroll : function (callback) { - updateScrollEvents(callback); - return this; - }, - - release : function () { - // TODO: could be unsafe. We might wanna release dragObject, etc. - documentEvents.stop('mousemove', handleMouseMove); - documentEvents.stop('mousedown', handleMouseDown); - documentEvents.stop('mouseup', handleMouseUp); - documentEvents.stop('touchmove', handleTouchMove); - documentEvents.stop('touchend', handleTouchEnd); - documentEvents.stop('touchcancel', handleTouchEnd); - - updateScrollEvents(null); - } - }; -}; -/** - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com - */ - -Viva.Input = Viva.Input || {}; -Viva.Input.domInputManager = function (graph, graphics) { - var nodeEvents = {}; - return { - /** - * Called by renderer to listen to drag-n-drop events from node. E.g. for CSS/SVG - * graphics we may listen to DOM events, whereas for WebGL the graphics - * should provide custom eventing mechanism. - * - * @param node - to be monitored. - * @param handlers - object with set of three callbacks: - * onStart: function(), - * onDrag: function(e, offset), - * onStop: function() - */ - bindDragNDrop : function (node, handlers) { - var events; - if (handlers) { - var nodeUI = graphics.getNodeUI(node.id); - events = Viva.Graph.Utils.dragndrop(nodeUI); - if (typeof handlers.onStart === 'function') { - events.onStart(handlers.onStart); - } - if (typeof handlers.onDrag === 'function') { - events.onDrag(handlers.onDrag); - } - if (typeof handlers.onStop === 'function') { - events.onStop(handlers.onStop); - } - - nodeEvents[node.id] = events; - } else if (( events = nodeEvents[node.id] )) { - events.release(); - delete nodeEvents[node.id]; - } - } - }; -}; +};/** + * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + */ + +Viva.Graph.Utils = Viva.Graph.Utils || {}; + +// TODO: I don't really like the way I implemented events. It looks clumsy and +// hard to understand. Refactor it. + +// TODO: This is really painful. Please don't use this class anymore, I will +// definitely depricate it or update its interface. + +/** + * Allows to start/stop listen to element's events. An element can be arbitrary + * DOM element, or object with eventuality behavior. + * + * To add eventuality behavior to arbitrary object 'obj' call + * Viva.Graph.Utils.event(obj).extend() method. + * After this call is made the object can use obj.fire(eventName, params) method, and listeners + * can listen to event by Viva.Graph.Utils.events(obj).on(eventName, callback) method. + */ +Viva.Graph.Utils.events = function (element) { + + /** + * Extends arbitrary object with fire method and allows it to be used with on/stop methods. + * + * This behavior is based on Crockford's eventuality example, but with a minor changes: + * - fire() method accepts parameters to pass to callbacks (instead of setting them in 'on' method) + * - on() method is replaced with addEventListener(), to let objects be used as a DOM objects. + * - behavoir contract is simplified to "string as event name"/"function as callback" convention. + * - removeEventListener() method added to let unsubscribe from events. + */ + var eventuality = function (that) { + var registry = {}; + + /** + * Fire an event on an object. The event is a string containing the name of the event + * Handlers registered by the 'addEventListener' method that match the event name + * will be invoked. + */ + that.fire = function (eventName, parameters) { + var registeredHandlers, + callback, + handler, + i; + + if (typeof eventName !== "string") { + throw "Only strings can be used as even type"; + } + + // If an array of handlers exist for this event, then + // loop through it and execute the handlers in order. + if (registry.hasOwnProperty(eventName)) { + registeredHandlers = registry[eventName]; + for (i = 0; i < registeredHandlers.length; ++i) { + handler = registeredHandlers[i]; + callback = handler.method; + callback(parameters); + } + } + + return this; + }; + + that.addEventListener = function (eventName, callback) { + if (typeof callback !== "function") { + throw "Only functions allowed to be callbacks"; + } + + var handler = { + method: callback + }; + if (registry.hasOwnProperty(eventName)) { + registry[eventName].push(handler); + } else { + registry[eventName] = [handler]; + } + + return this; + }; + + that.removeEventListener = function (eventName, callback) { + if (typeof callback !== "function") { + throw "Only functions allowed to be callbacks"; + } + + if (registry.hasOwnProperty(eventName)) { + var handlers = registry[eventName], + i; + + for (i = 0; i < handlers.length; ++i) { + if (handlers[i].callback === callback) { + handlers.splice(i); + break; + } + } + } + + return this; + }; + + that.removeAllListeners = function () { + var eventName; + for (eventName in registry) { + if (registry.hasOwnProperty(eventName)) { + delete registry[eventName]; + } + } + }; + + return that; + }; + + return { + /** + * Registes callback to be called when element fires event with given event name. + */ + on : function (eventName, callback) { + if (element.addEventListener) {// W3C DOM and eventuality objecets. + element.addEventListener(eventName, callback, false); + } else if (element.attachEvent) { // IE DOM + element.attachEvent("on" + eventName, callback); + } + + return this; + }, + + /** + * Unsubcribes from object's events. + */ + stop : function (eventName, callback) { + if (element.removeEventListener) { + element.removeEventListener(eventName, callback, false); + } else if (element.detachEvent) { + element.detachEvent("on" + eventName, callback); + } + }, + + /** + * Adds eventuality to arbitrary JavaScript object. Eventuality adds + * fire(), addEventListner() and removeEventListners() to the target object. + * + * This is required if you want to use object with on(), stop() methods. + */ + extend : function () { + return eventuality(element); + } + }; +}; +/** + * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + */ + +Viva.Graph.Utils = Viva.Graph.Utils || {}; + +// TODO: Move to input namespace +// TODO: Methods should be extracted into the prototype. This class +// does not need to consume so much memory for every tracked element +Viva.Graph.Utils.dragndrop = function (element) { + var start, + drag, + end, + scroll, + prevSelectStart, + prevDragStart, + documentEvents = Viva.Graph.Utils.events(window.document), + elementEvents = Viva.Graph.Utils.events(element), + findElementPosition = Viva.Graph.Utils.findElementPosition, + + startX = 0, + startY = 0, + dragObject, + touchInProgress = false, + pinchZoomLength = 0, + + getMousePos = function (e) { + var posx = 0, + posy = 0; + + e = e || window.event; + + if (e.pageX || e.pageY) { + posx = e.pageX; + posy = e.pageY; + } else if (e.clientX || e.clientY) { + posx = e.clientX + window.document.body.scrollLeft + window.document.documentElement.scrollLeft; + posy = e.clientY + window.document.body.scrollTop + window.document.documentElement.scrollTop; + } + + return [posx, posy]; + }, + + move = function (e, clientX, clientY) { + if (drag) { + drag(e, {x : clientX - startX, y : clientY - startY }); + } + + startX = clientX; + startY = clientY; + }, + + stopPropagation = function (e) { + if (e.stopPropagation) { e.stopPropagation(); } else { e.cancelBubble = true; } + }, + preventDefault = function (e) { + if (e.preventDefault) { e.preventDefault(); } + }, + + handleDisabledEvent = function (e) { + stopPropagation(e); + return false; + }, + + handleMouseMove = function (e) { + e = e || window.event; + + move(e, e.clientX, e.clientY); + }, + + handleMouseDown = function (e) { + e = e || window.event; + if (touchInProgress) { + // modern browsers will fire mousedown for touch events too + // we do not want this, since touch is handled separately. + stopPropagation(e); + return false; + } + // for IE, left click == 1 + // for Firefox, left click == 0 + var isLeftButton = ((e.button === 1 && window.event !== null) || e.button === 0); + + if (isLeftButton) { + startX = e.clientX; + startY = e.clientY; + + // TODO: bump zIndex? + dragObject = e.target || e.srcElement; + + if (start) { start(e, {x: startX, y : startY}); } + + documentEvents.on('mousemove', handleMouseMove); + documentEvents.on('mouseup', handleMouseUp); + + + stopPropagation(e); + // TODO: What if event already there? Not bullet proof: + prevSelectStart = window.document.onselectstart; + prevDragStart = window.document.ondragstart; + + window.document.onselectstart = handleDisabledEvent; + dragObject.ondragstart = handleDisabledEvent; + + // prevent text selection (except IE) + return false; + } + }, + + handleMouseUp = function (e) { + e = e || window.event; + + documentEvents.stop('mousemove', handleMouseMove); + documentEvents.stop('mouseup', handleMouseUp); + + window.document.onselectstart = prevSelectStart; + dragObject.ondragstart = prevDragStart; + dragObject = null; + if (end) { end(e); } + }, + + handleMouseWheel = function (e) { + if (typeof scroll !== 'function') { + return; + } + + e = e || window.event; + if (e.preventDefault) { + e.preventDefault(); + } + + e.returnValue = false; + var delta, + mousePos = getMousePos(e), + elementOffset = findElementPosition(element), + relMousePos = { + x: mousePos[0] - elementOffset[0], + y: mousePos[1] - elementOffset[1] + }; + + if (e.wheelDelta) { + delta = e.wheelDelta / 360; // Chrome/Safari + } else { + delta = e.detail / -9; // Mozilla + } + + scroll(e, delta, relMousePos); + }, + + updateScrollEvents = function (scrollCallback) { + if (!scroll && scrollCallback) { + // client is interested in scrolling. Start listening to events: + if (Viva.BrowserInfo.browser === 'webkit') { + element.addEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari + } else { + element.addEventListener('DOMMouseScroll', handleMouseWheel, false); // Others + } + } else if (scroll && !scrollCallback) { + if (Viva.BrowserInfo.browser === 'webkit') { + element.removeEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari + } else { + element.removeEventListener('DOMMouseScroll', handleMouseWheel, false); // Others + } + } + + scroll = scrollCallback; + }, + + getPinchZoomLength = function(finger1, finger2) { + return (finger1.clientX - finger2.clientX) * (finger1.clientX - finger2.clientX) + + (finger1.clientY - finger2.clientY) * (finger1.clientY - finger2.clientY); + }, + + handleTouchMove = function (e) { + if (e.touches.length === 1) { + stopPropagation(e); + + var touch = e.touches[0]; + move(e, touch.clientX, touch.clientY); + } else if (e.touches.length === 2) { + // it's a zoom: + var currentPinchLength = getPinchZoomLength(e.touches[0], e.touches[1]); + var delta = 0; + if (currentPinchLength < pinchZoomLength) { + delta = -1; + } else if (currentPinchLength > pinchZoomLength) { + delta = 1; + } + scroll(e, delta, {x: e.touches[0].clientX, y: e.touches[0].clientY}); + pinchZoomLength = currentPinchLength; + stopPropagation(e); + preventDefault(e); + } + }, + + handleTouchEnd = function (e) { + touchInProgress = false; + documentEvents.stop('touchmove', handleTouchMove); + documentEvents.stop('touchend', handleTouchEnd); + documentEvents.stop('touchcancel', handleTouchEnd); + dragObject = null; + if (end) { end(e); } + }, + + handleSignleFingerTouch = function (e, touch) { + stopPropagation(e); + preventDefault(e); + + startX = touch.clientX; + startY = touch.clientY; + + dragObject = e.target || e.srcElement; + + if (start) { start(e, {x: startX, y : startY}); } + // TODO: can I enter into the state when touch is in progress + // but it's still a single finger touch? + if (!touchInProgress) { + touchInProgress = true; + documentEvents.on('touchmove', handleTouchMove); + documentEvents.on('touchend', handleTouchEnd); + documentEvents.on('touchcancel', handleTouchEnd); + } + }, + + handleTouchStart = function (e) { + console.log('Touch start for ', element); + if (e.touches.length === 1) { + return handleSignleFingerTouch(e, e.touches[0]); + } else if (e.touches.length === 2) { + // handleTouchMove() will care about pinch zoom. + stopPropagation(e); + preventDefault(e); + + pinchZoomLength = getPinchZoomLength(e.touches[0], e.touches[1]); + + } + // don't care about the rest. + }; + + + elementEvents.on('mousedown', handleMouseDown); + elementEvents.on('touchstart', handleTouchStart); + + return { + onStart : function (callback) { + start = callback; + return this; + }, + + onDrag : function (callback) { + drag = callback; + return this; + }, + + onStop : function (callback) { + end = callback; + return this; + }, + + /** + * Occurs when mouse wheel event happens. callback = function(e, scrollDelta, scrollPoint); + */ + onScroll : function (callback) { + updateScrollEvents(callback); + return this; + }, + + release : function () { + // TODO: could be unsafe. We might wanna release dragObject, etc. + documentEvents.stop('mousemove', handleMouseMove); + documentEvents.stop('mousedown', handleMouseDown); + documentEvents.stop('mouseup', handleMouseUp); + documentEvents.stop('touchmove', handleTouchMove); + documentEvents.stop('touchend', handleTouchEnd); + documentEvents.stop('touchcancel', handleTouchEnd); + + updateScrollEvents(null); + } + }; +}; +/** + * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + */ + +Viva.Input = Viva.Input || {}; +Viva.Input.domInputManager = function (graph, graphics) { + var nodeEvents = {}; + return { + /** + * Called by renderer to listen to drag-n-drop events from node. E.g. for CSS/SVG + * graphics we may listen to DOM events, whereas for WebGL the graphics + * should provide custom eventing mechanism. + * + * @param node - to be monitored. + * @param handlers - object with set of three callbacks: + * onStart: function(), + * onDrag: function(e, offset), + * onStop: function() + */ + bindDragNDrop : function (node, handlers) { + var events; + if (handlers) { + var nodeUI = graphics.getNodeUI(node.id); + events = Viva.Graph.Utils.dragndrop(nodeUI); + if (typeof handlers.onStart === 'function') { + events.onStart(handlers.onStart); + } + if (typeof handlers.onDrag === 'function') { + events.onDrag(handlers.onDrag); + } + if (typeof handlers.onStop === 'function') { + events.onStop(handlers.onStop); + } + + nodeEvents[node.id] = events; + } else if (( events = nodeEvents[node.id] )) { + events.release(); + delete nodeEvents[node.id]; + } + } + }; +}; /** * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com */ @@ -760,232 +760,232 @@ Viva.Graph.Utils = Viva.Graph.Utils || {}; } }; }; -}());Viva.Graph.geom = function () { - - return { - // function from Graphics GEM to determine lines intersection: - // http://www.opensource.apple.com/source/graphviz/graphviz-498/graphviz/dynagraph/common/xlines.c - intersect : function (x1, y1, x2, y2, // first line segment - x3, y3, x4, y4) { // second line segment - var a1, a2, b1, b2, c1, c2, /* Coefficients of line eqns. */ - r1, r2, r3, r4, /* 'Sign' values */ - denom, offset, num, /* Intermediate values */ - result = { x: 0, y : 0}; - - /* Compute a1, b1, c1, where line joining points 1 and 2 - * is "a1 x + b1 y + c1 = 0". - */ - a1 = y2 - y1; - b1 = x1 - x2; - c1 = x2 * y1 - x1 * y2; - - /* Compute r3 and r4. - */ - r3 = a1 * x3 + b1 * y3 + c1; - r4 = a1 * x4 + b1 * y4 + c1; - - /* Check signs of r3 and r4. If both point 3 and point 4 lie on - * same side of line 1, the line segments do not intersect. - */ - - if (r3 !== 0 && r4 !== 0 && ((r3 >= 0) === (r4 >= 4))) { - return null; //no itersection. - } - - /* Compute a2, b2, c2 */ - a2 = y4 - y3; - b2 = x3 - x4; - c2 = x4 * y3 - x3 * y4; - - /* Compute r1 and r2 */ - - r1 = a2 * x1 + b2 * y1 + c2; - r2 = a2 * x2 + b2 * y2 + c2; - - /* Check signs of r1 and r2. If both point 1 and point 2 lie - * on same side of second line segment, the line segments do - * not intersect. - */ - if (r1 !== 0 && r2 !== 0 && ((r1 >= 0) === (r2 >= 0))) { - return null; // no intersection; - } - /* Line segments intersect: compute intersection point. - */ - - denom = a1 * b2 - a2 * b1; - if (denom === 0) { - return null; // Actually collinear.. - } - - offset = denom < 0 ? -denom / 2 : denom / 2; - offset = 0.0; - - /* The denom/2 is to get rounding instead of truncating. It - * is added or subtracted to the numerator, depending upon the - * sign of the numerator. - */ - - - num = b1 * c2 - b2 * c1; - result.x = (num < 0 ? num - offset : num + offset) / denom; - - num = a2 * c1 - a1 * c2; - result.y = (num < 0 ? num - offset : num + offset) / denom; - - return result; - }, - - /** - * Returns intersection point of the rectangle defined by - * left, top, right, bottom and a line starting in x1, y1 - * and ending in x2, y2; - */ - intersectRect : function (left, top, right, bottom, x1, y1, x2, y2) { - return this.intersect(left, top, left, bottom, x1, y1, x2, y2) || - this.intersect(left, bottom, right, bottom, x1, y1, x2, y2) || - this.intersect(right, bottom, right, top, x1, y1, x2, y2) || - this.intersect(right, top, left, top, x1, y1, x2, y2); - }, - - convexHull : function (points) { - var polarAngleSort = function (basePoint, points) { - var cosAngle = function (p) { - var dx = p.x - basePoint.x, - dy = p.y - basePoint.y, - sign = dx > 0 ? 1 : -1; - - // We use squared dx, to avoid Sqrt opertion and improve performance. - // To avoid sign loss during dx * dx operation we precompute its sign: - return sign * dx * dx / (dx * dx + dy * dy); - }, - - sortedPoints = points.sort(function (p1, p2) { - return cosAngle(p2) - cosAngle(p1); - }), - - // If more than one point has the same angle, remove all but the one that is farthest from basePoint: - lastPoint = sortedPoints[0], - lastAngle = cosAngle(lastPoint), - dx = lastPoint.x - basePoint.x, - dy = lastPoint.y - basePoint.y, - lastDistance = dx * dx + dy * dy, - curDistance, - i; - - for (i = 1; i < sortedPoints.length; ++i) { - lastPoint = sortedPoints[i]; - var angle = cosAngle(lastPoint); - if (angle === lastAngle) { - dx = lastPoint.x - basePoint.x; - dy = lastPoint.y - basePoint.y; - curDistance = dx * dx + dy * dy; - - if (curDistance < lastDistance) { - sortedPoints.splice(i, 1); - } else { - sortedPoints.splice(i - 1, 1); - } - } else { - lastAngle = angle; - } - } - - return sortedPoints; - }, - - /** - * Returns true if angle formed by points p0, p1, p2 makes left turn. - * (counterclockwise) - */ - ccw = function (p0, p1, p2) { - return ((p2.x - p0.x) * (p1.y - p0.y) - (p2.y - p0.y) * (p1.x - p0.x)) < 0; - }; - - if (points.length < 3) { - return points; // This one is easy... Not precise, but should be enough for now. - } - - // let p0 be the point in Q with the minimum y-coordinate, or the leftmost - // such point in case of a tie - var p0Idx = 0, - i; - for (i = 0; i < points.length; ++i) { - if (points[i].y < points[p0Idx].y) { - p0Idx = i; - } else if (points[i].y === points[p0Idx].y && points[i].x < points[p0Idx].x) { - p0Idx = i; - } - } - - var p0 = points[p0Idx]; - // let be the remaining points - points.splice(p0Idx, 1); - // sorted by polar angle in counterclockwise order around p0 - var sortedPoints = polarAngleSort(p0, points); - if (sortedPoints.length < 2) { - return sortedPoints; - } - - // let S be empty stack - var s = []; - s.push(p0); - s.push(sortedPoints[0]); - s.push(sortedPoints[1]); - var sLength = s.length; - for (i = 2; i < sortedPoints.length; ++i) { - while (!ccw(s[sLength - 2], s[sLength - 1], sortedPoints[i])) { - s.pop(); - sLength -= 1; - } - - s.push(sortedPoints[i]); - sLength += 1; - } - - return s; - } - }; -};/** - * Very generic rectangle. - */ -Viva.Graph.Rect = function (x1, y1, x2, y2) { - this.x1 = x1 || 0; - this.y1 = y1 || 0; - this.x2 = x2 || 0; - this.y2 = y2 || 0; -}; - -/** - * Very generic two-dimensional point. - */ -Viva.Graph.Point2d = function (x, y) { - this.x = x || 0; - this.y = y || 0; -}; - -/** - * Internal structure to represent node; - */ -Viva.Graph.Node = function (id) { - this.id = id; - this.links = []; - this.data = null; -}; - -/** - * Internal structure to represent links; - */ -Viva.Graph.Link = function (fromId, toId, data, id) { - this.fromId = fromId; - this.toId = toId; - this.data = data; - this.id = id; -}; -/** - * @fileOverview Contains definition of the core graph object. - * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com - */ +}());Viva.Graph.geom = function () { + + return { + // function from Graphics GEM to determine lines intersection: + // http://www.opensource.apple.com/source/graphviz/graphviz-498/graphviz/dynagraph/common/xlines.c + intersect : function (x1, y1, x2, y2, // first line segment + x3, y3, x4, y4) { // second line segment + var a1, a2, b1, b2, c1, c2, /* Coefficients of line eqns. */ + r1, r2, r3, r4, /* 'Sign' values */ + denom, offset, num, /* Intermediate values */ + result = { x: 0, y : 0}; + + /* Compute a1, b1, c1, where line joining points 1 and 2 + * is "a1 x + b1 y + c1 = 0". + */ + a1 = y2 - y1; + b1 = x1 - x2; + c1 = x2 * y1 - x1 * y2; + + /* Compute r3 and r4. + */ + r3 = a1 * x3 + b1 * y3 + c1; + r4 = a1 * x4 + b1 * y4 + c1; + + /* Check signs of r3 and r4. If both point 3 and point 4 lie on + * same side of line 1, the line segments do not intersect. + */ + + if (r3 !== 0 && r4 !== 0 && ((r3 >= 0) === (r4 >= 4))) { + return null; //no itersection. + } + + /* Compute a2, b2, c2 */ + a2 = y4 - y3; + b2 = x3 - x4; + c2 = x4 * y3 - x3 * y4; + + /* Compute r1 and r2 */ + + r1 = a2 * x1 + b2 * y1 + c2; + r2 = a2 * x2 + b2 * y2 + c2; + + /* Check signs of r1 and r2. If both point 1 and point 2 lie + * on same side of second line segment, the line segments do + * not intersect. + */ + if (r1 !== 0 && r2 !== 0 && ((r1 >= 0) === (r2 >= 0))) { + return null; // no intersection; + } + /* Line segments intersect: compute intersection point. + */ + + denom = a1 * b2 - a2 * b1; + if (denom === 0) { + return null; // Actually collinear.. + } + + offset = denom < 0 ? -denom / 2 : denom / 2; + offset = 0.0; + + /* The denom/2 is to get rounding instead of truncating. It + * is added or subtracted to the numerator, depending upon the + * sign of the numerator. + */ + + + num = b1 * c2 - b2 * c1; + result.x = (num < 0 ? num - offset : num + offset) / denom; + + num = a2 * c1 - a1 * c2; + result.y = (num < 0 ? num - offset : num + offset) / denom; + + return result; + }, + + /** + * Returns intersection point of the rectangle defined by + * left, top, right, bottom and a line starting in x1, y1 + * and ending in x2, y2; + */ + intersectRect : function (left, top, right, bottom, x1, y1, x2, y2) { + return this.intersect(left, top, left, bottom, x1, y1, x2, y2) || + this.intersect(left, bottom, right, bottom, x1, y1, x2, y2) || + this.intersect(right, bottom, right, top, x1, y1, x2, y2) || + this.intersect(right, top, left, top, x1, y1, x2, y2); + }, + + convexHull : function (points) { + var polarAngleSort = function (basePoint, points) { + var cosAngle = function (p) { + var dx = p.x - basePoint.x, + dy = p.y - basePoint.y, + sign = dx > 0 ? 1 : -1; + + // We use squared dx, to avoid Sqrt opertion and improve performance. + // To avoid sign loss during dx * dx operation we precompute its sign: + return sign * dx * dx / (dx * dx + dy * dy); + }, + + sortedPoints = points.sort(function (p1, p2) { + return cosAngle(p2) - cosAngle(p1); + }), + + // If more than one point has the same angle, remove all but the one that is farthest from basePoint: + lastPoint = sortedPoints[0], + lastAngle = cosAngle(lastPoint), + dx = lastPoint.x - basePoint.x, + dy = lastPoint.y - basePoint.y, + lastDistance = dx * dx + dy * dy, + curDistance, + i; + + for (i = 1; i < sortedPoints.length; ++i) { + lastPoint = sortedPoints[i]; + var angle = cosAngle(lastPoint); + if (angle === lastAngle) { + dx = lastPoint.x - basePoint.x; + dy = lastPoint.y - basePoint.y; + curDistance = dx * dx + dy * dy; + + if (curDistance < lastDistance) { + sortedPoints.splice(i, 1); + } else { + sortedPoints.splice(i - 1, 1); + } + } else { + lastAngle = angle; + } + } + + return sortedPoints; + }, + + /** + * Returns true if angle formed by points p0, p1, p2 makes left turn. + * (counterclockwise) + */ + ccw = function (p0, p1, p2) { + return ((p2.x - p0.x) * (p1.y - p0.y) - (p2.y - p0.y) * (p1.x - p0.x)) < 0; + }; + + if (points.length < 3) { + return points; // This one is easy... Not precise, but should be enough for now. + } + + // let p0 be the point in Q with the minimum y-coordinate, or the leftmost + // such point in case of a tie + var p0Idx = 0, + i; + for (i = 0; i < points.length; ++i) { + if (points[i].y < points[p0Idx].y) { + p0Idx = i; + } else if (points[i].y === points[p0Idx].y && points[i].x < points[p0Idx].x) { + p0Idx = i; + } + } + + var p0 = points[p0Idx]; + // let be the remaining points + points.splice(p0Idx, 1); + // sorted by polar angle in counterclockwise order around p0 + var sortedPoints = polarAngleSort(p0, points); + if (sortedPoints.length < 2) { + return sortedPoints; + } + + // let S be empty stack + var s = []; + s.push(p0); + s.push(sortedPoints[0]); + s.push(sortedPoints[1]); + var sLength = s.length; + for (i = 2; i < sortedPoints.length; ++i) { + while (!ccw(s[sLength - 2], s[sLength - 1], sortedPoints[i])) { + s.pop(); + sLength -= 1; + } + + s.push(sortedPoints[i]); + sLength += 1; + } + + return s; + } + }; +};/** + * Very generic rectangle. + */ +Viva.Graph.Rect = function (x1, y1, x2, y2) { + this.x1 = x1 || 0; + this.y1 = y1 || 0; + this.x2 = x2 || 0; + this.y2 = y2 || 0; +}; + +/** + * Very generic two-dimensional point. + */ +Viva.Graph.Point2d = function (x, y) { + this.x = x || 0; + this.y = y || 0; +}; + +/** + * Internal structure to represent node; + */ +Viva.Graph.Node = function (id) { + this.id = id; + this.links = []; + this.data = null; +}; + +/** + * Internal structure to represent links; + */ +Viva.Graph.Link = function (fromId, toId, data, id) { + this.fromId = fromId; + this.toId = toId; + this.data = data; + this.id = id; +}; +/** + * @fileOverview Contains definition of the core graph object. + * + * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + */ /** * @namespace Represents a graph data structure. @@ -1516,11 +1516,11 @@ Viva.Graph.Physics.eulerIntegrator = function () { body.location.x += dx; body.location.y += dy; - tx += dx; - ty += dy; + tx += Math.abs(dx); + ty += Math.abs(dy); } - return (tx * tx + ty * ty)/max; + return (tx + ty)/max; } }; }; @@ -2082,3755 +2082,3762 @@ Viva.Graph.Physics.forceSimulator = function (forceIntegrator) { } }; }; -// I don't like to suppress this, but I'm afraid 'force_directed_body' -// could already be used by someone. Don't want to break it now. -/* jshint camelcase:false */ - -Viva.Graph.Layout = Viva.Graph.Layout || {}; -Viva.Graph.Layout.forceDirected = function(graph, settings) { - if (!graph) { - throw { - message: 'Graph structure cannot be undefined' - }; - } +// I don't like to suppress this, but I'm afraid 'force_directed_body' +// could already be used by someone. Don't want to break it now. +/* jshint camelcase:false */ + +Viva.Graph.Layout = Viva.Graph.Layout || {}; +Viva.Graph.Layout.forceDirected = function(graph, settings) { + if (!graph) { + throw { + message: 'Graph structure cannot be undefined' + }; + } + + settings = Viva.lazyExtend(settings, { + /** + * Ideal length for links (springs in physical model). + */ + springLength: 80, + + /** + * Hook's law coefficient. 1 - solid spring. + */ + springCoeff: 0.0002, + + /** + * Coulomb's law coefficient. It's used to repel nodes thus should be negative + * if you make it positive nodes start attract each other :). + */ + gravity: -1.2, + + /** + * Theta coeffiecient from Barnes Hut simulation. Ranged between (0, 1). + * The closer it's to 1 the more nodes algorithm will have to go through. + * Setting it to one makes Barnes Hut simulation no different from + * brute-force forces calculation (each node is considered). + */ + theta: 0.8, + + /** + * Drag force coefficient. Used to slow down system, thus should be less than 1. + * The closer it is to 0 the less tight system will be. + */ + dragCoeff: 0.02, + + /** + * Allows to transfor physical spring associated with a link. this allows clients + * to specify custom length for a link. + * + * @param {Viva.Graph.Link} link actual link for which transform is performed + * @param {Viva.Graph.Physics.Spring} spring physical spring which is associated with + * a link. Most interesting property will be 'length' + * + * @example + * // Let's say your graph represent friendship. Each link has associated + * // 'strength' of connection, distributed from 0 (not a strong connection) to + * // 1 (very strong connection) + * // + * // You want your graph to have uniformly distributed links, but stronger + * // connection should pull nodes closer: + * + * graph.addLink(user1, user2, { friendshipStrength: 0.9 }); + * var layout = Viva.Graph.Layout.forceDirected(graph, { + * springLength: 80, // 80 pixels is our ideal link length + * springTransform: function (link, spring) { + * // We can set custom desired length of a spring, based on + * // link's data: + * spring.length = 80 * (1 - link.data.friendshipStrength); + * } + * } + */ + springTransform: function (link, spring) { + // By default, it is a no-op + }, + + /** + * Default time step (dt) for forces integration + */ + timeStep : 20, + + /** + * Maximum movement of the system which can be considered as stabilized + */ + stableThreshold: 0.009 + }); + + var forceSimulator = Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()), + nbodyForce = Viva.Graph.Physics.nbodyForce({ + gravity: settings.gravity, + theta: settings.theta + }), + springForce = Viva.Graph.Physics.springForce({ + length: settings.springLength, + coeff: settings.springCoeff + }), + dragForce = Viva.Graph.Physics.dragForce({ + coeff: settings.dragCoeff + }), + graphRect = new Viva.Graph.Rect(), + random = Viva.random('ted.com', 103, 114, 101, 97, 116), + + nodeBodies = {}, + getBestNodePosition = function(node) { + // TODO: Initial position could be picked better, e.g. take into + // account all neighbouring nodes/links, not only one. + // How about center of mass? + if (node.position) { + return node.position; + } + var baseX = (graphRect.x1 + graphRect.x2) / 2, + baseY = (graphRect.y1 + graphRect.y2) / 2, + springLength = settings.springLength; + + if (node.links && node.links.length > 0) { + var firstLink = node.links[0], + otherNode = firstLink.fromId !== node.id ? nodeBodies[firstLink.fromId] : nodeBodies[firstLink.toId]; + if (otherNode && otherNode.location) { + baseX = otherNode.location.x; + baseY = otherNode.location.y; + } + } + + return { + x: baseX + random.next(springLength) - springLength / 2, + y: baseY + random.next(springLength) - springLength / 2 + }; + }, + + getBody = function (nodeId) { + return nodeBodies[nodeId]; + }, + + releaseBody = function (nodeId) { + nodeBodies[nodeId] = null; + delete nodeBodies[nodeId]; + }, + + springs = {}, + + updateBodyMass = function(nodeId) { + var body = getBody(nodeId); + body.mass = 1 + graph.getLinks(nodeId).length / 3.0; + }, + + isNodePinned = function(node) { + return (node && (node.isPinned || (node.data && node.data.isPinned))); + }, + + isBodyPinned = function (body) { + return body.isPinned; + }, + + initNode = function(nodeId) { + var body = getBody(nodeId); + if (!body) { + var node = graph.getNode(nodeId); + if (!node) { + return; // what are you doing? + } + + body = new Viva.Graph.Physics.Body(); + nodeBodies[nodeId] = body; + var position = getBestNodePosition(node); + body.loc(position); + updateBodyMass(nodeId); + + if (isNodePinned(node)) { + body.isPinned = true; + } + forceSimulator.addBody(body); + } + }, + + initNodeObject = function (node) { + initNode(node.id); + }, + + releaseNode = function(node) { + var body = getBody(node.id); + if (body) { + releaseBody(node.id); + + forceSimulator.removeBody(body); + if (graph.getNodesCount() === 0) { + graphRect.x1 = graphRect.y1 = 0; + graphRect.x2 = graphRect.y2 = 0; + } + } + }, + + initLink = function(link) { + updateBodyMass(link.fromId); + updateBodyMass(link.toId); + + var fromBody = getBody(link.fromId), + toBody = getBody(link.toId), + spring = forceSimulator.addSpring(fromBody, toBody, -1.0, link.weight); + + settings.springTransform(link, spring); + springs[link.id] = spring; + }, + + releaseLink = function(link) { + var spring = springs[link.id]; + if (spring) { + var from = graph.getNode(link.fromId), + to = graph.getNode(link.toId); + if (from) { + updateBodyMass(from.id); + } + if (to) { + updateBodyMass(to.id); + } + delete springs[link.id]; + + forceSimulator.removeSpring(spring); + } + }, + + onGraphChanged = function(changes) { + for (var i = 0; i < changes.length; ++i) { + var change = changes[i]; + if (change.changeType === 'add') { + if (change.node) { + initNode(change.node.id); + } + if (change.link) { + initLink(change.link); + } + } else if (change.changeType === 'remove') { + if (change.node) { + releaseNode(change.node); + } + if (change.link) { + releaseLink(change.link); + } + } + } + }, + + initSimulator = function() { + graph.forEachNode(initNodeObject); + graph.forEachLink(initLink); + graph.addEventListener('changed', onGraphChanged); + }, + + updateNodePositions = function() { + var x1 = Number.MAX_VALUE, + y1 = Number.MAX_VALUE, + x2 = Number.MIN_VALUE, + y2 = Number.MIN_VALUE; + + if (graph.getNodesCount() === 0) { + return; + } + for (var key in nodeBodies) { + if (nodeBodies.hasOwnProperty(key)) { + // how about pinned nodes? + var body = nodeBodies[key]; + if (isBodyPinned(body)) { + body.location.x = body.prevLocation.x; + body.location.y = body.prevLocation.y; + } else { + body.prevLocation.x = body.location.x; + body.prevLocation.y = body.location.y; + } + if (body.location.x < x1) { + x1 = body.location.x; + } + if (body.location.x > x2) { + x2 = body.location.x; + } + if (body.location.y < y1) { + y1 = body.location.y; + } + if (body.location.y > y2) { + y2 = body.location.y; + } + } + } + + graphRect.x1 = x1; + graphRect.x2 = x2; + graphRect.y1 = y1; + graphRect.y2 = y2; + }; + + forceSimulator.setSpringForce(springForce); + forceSimulator.setNbodyForce(nbodyForce); + forceSimulator.setDragForce(dragForce); + + initSimulator(); + + return { + /** + * Attempts to layout graph within given number of iterations. + * + * @param {integer} [iterationsCount] number of algorithm's iterations. + */ + run: function(iterationsCount) { + var i; + iterationsCount = iterationsCount || 50; + + for (i = 0; i < iterationsCount; ++i) { + this.step(); + } + }, + + /** + * Performs one step of iterative layout algorithm + */ + step: function() { + var energy = forceSimulator.run(settings.timeStep); + updateNodePositions(); + + return energy < settings.stableThreshold; + }, + + /* + * Checks whether given node is pinned; + */ + isNodePinned: function (node) { + var body = getBody(node.id); + if (body) { + return isBodyPinned(body); + } + }, + + /* + * Requests layout algorithm to pin/unpin node to its current position + * Pinned nodes should not be affected by layout algorithm and always + * remain at their position + */ + pinNode: function (node, isPinned) { + var body = getBody(node.id); + body.isPinned = !!isPinned; + }, + + /* + * Gets position of a node by its id. If node was not seen by this + * layout algorithm undefined value is returned; + */ + getNodePosition: function (nodeId) { + var body = getBody(nodeId); + if (!body) { + initNode(nodeId); + body = getBody(nodeId); + } + return body && body.location; + }, + + /** + * Returns {from, to} position of a link. + */ + getLinkPosition: function (link) { + var from = this.getNodePosition(link.fromId), + to = this.getNodePosition(link.toId); + + return { + from : from, + to : to + }; + }, + + /** + * Sets position of a node to a given coordinates + */ + setNodePosition: function (node, x, y) { + var body = getBody(node.id); + if (body) { + body.prevLocation.x = body.location.x = x; + body.prevLocation.y = body.location.y = y; + } + }, + + /** + * Returns rectangle structure {x1, y1, x2, y2}, which represents + * current space occupied by graph. + */ + getGraphRect: function() { + return graphRect; + }, + + /** + * Request to release all resources + */ + dispose: function() { + graph.removeEventListener('change', onGraphChanged); + }, + + // Layout specific methods + /** + * Gets or sets current desired length of the edge. + * + * @param length new desired length of the springs (aka edge, aka link). + * if this parameter is empty then old spring length is returned. + */ + springLength: function(length) { + if (arguments.length === 1) { + springForce.options({ + length: length + }); + return this; + } + + return springForce.options().length; + }, + + /** + * Gets or sets current spring coeffiсient. + * + * @param coeff new spring coeffiсient. + * if this parameter is empty then its old value returned. + */ + springCoeff: function(coeff) { + if (arguments.length === 1) { + springForce.options({ + coeff: coeff + }); + return this; + } + + return springForce.options().coeff; + }, + + /** + * Gets or sets current gravity in the nbody simulation. + * + * @param g new gravity constant. + * if this parameter is empty then its old value returned. + */ + gravity: function(g) { + if (arguments.length === 1) { + nbodyForce.options({ + gravity: g + }); + return this; + } + + return nbodyForce.options().gravity; + }, + + /** + * Gets or sets current theta value in the nbody simulation. + * + * @param t new theta coeffiсient. + * if this parameter is empty then its old value returned. + */ + theta: function(t) { + if (arguments.length === 1) { + nbodyForce.options({ + theta: t + }); + return this; + } + + return nbodyForce.options().theta; + }, + + /** + * Gets or sets current theta value in the nbody simulation. + * + * @param dragCoeff new drag coeffiсient. + * if this parameter is empty then its old value returned. + */ + drag: function(dragCoeff) { + if (arguments.length === 1) { + dragForce.options({ + coeff: dragCoeff + }); + return this; + } + + return dragForce.options().coeff; + } + }; +}; +Viva.Graph.Layout = Viva.Graph.Layout || {}; + +/** + * Does not really perform any layouting algorithm but is compliant + * with renderer interface. Allowing clients to provide specific positioning + * callback and get static layout of the graph + * + * @param {Viva.Graph.graph} graph to layout + * @param {Object} userSettings + */ +Viva.Graph.Layout.constant = function (graph, userSettings) { + userSettings = Viva.lazyExtend(userSettings, { + maxX : 1024, + maxY : 1024, + seed : 'Deterministic randomness made me do this' + }); + // This class simply follows API, it does not use some of the arguments: + /*jshint unused: false */ + var rand = Viva.random(userSettings.seed), + graphRect = new Viva.Graph.Rect(Number.MAX_VALUE, Number.MAX_VALUE, Number.MIN_VALUE, Number.MIN_VALUE), + + placeNodeCallback = function (node) { + return new Viva.Graph.Point2d(rand.next(userSettings.maxX), rand.next(userSettings.maxY)); + }, + + updateGraphRect = function (position, graphRect) { + if (position.x < graphRect.x1) { graphRect.x1 = position.x; } + if (position.x > graphRect.x2) { graphRect.x2 = position.x; } + if (position.y < graphRect.y1) { graphRect.y1 = position.y; } + if (position.y > graphRect.y2) { graphRect.y2 = position.y; } + }, + + layoutNodes = typeof Object.create === 'function' ? Object.create(null) : {}, + + ensureNodeInitialized = function (node) { + if (!node) { return; } + layoutNodes[node.id] = placeNodeCallback(node); + updateGraphRect(layoutNodes[node.id], graphRect); + }, + + updateNodePositions = function () { + if (graph.getNodesCount() === 0) { return; } + + graphRect.x1 = Number.MAX_VALUE; + graphRect.y1 = Number.MAX_VALUE; + graphRect.x2 = Number.MIN_VALUE; + graphRect.y2 = Number.MIN_VALUE; + + graph.forEachNode(ensureNodeInitialized); + }, + + onGraphChanged = function(changes) { + for (var i = 0; i < changes.length; ++i) { + var change = changes[i]; + if (change.node) { + if (change.changeType === 'add') { + ensureNodeInitialized(change.node); + } else { + delete layoutNodes[change.node.id]; + } + } + } + }; + + graph.addEventListener('changed', onGraphChanged); + + return { + /** + * Attempts to layout graph within given number of iterations. + * + * @param {integer} [iterationsCount] number of algorithm's iterations. + * The constant layout ignores this parameter. + */ + run : function (iterationsCount) { + this.step(); + }, + + /** + * One step of layout algorithm. + */ + step : function () { + updateNodePositions(); + + return true; // no need to continue. + }, + + /** + * Returns rectangle structure {x1, y1, x2, y2}, which represents + * current space occupied by graph. + */ + getGraphRect : function () { + return graphRect; + }, + + /** + * Request to release all resources + */ + dispose : function () { + graph.removeEventListener('change', onGraphChanged); + }, + + /* + * Checks whether given node is pinned; all nodes in this layout are pinned. + */ + isNodePinned: function (node) { + return true; + }, + + /* + * Requests layout algorithm to pin/unpin node to its current position + * Pinned nodes should not be affected by layout algorithm and always + * remain at their position + */ + pinNode: function (node, isPinned) { + // noop + }, + + /* + * Gets position of a node by its id. If node was not seen by this + * layout algorithm undefined value is returned; + */ + getNodePosition: function (nodeId) { + var pos = layoutNodes[nodeId]; + if (!pos) { + ensureNodeInitialized(graph.getNode(nodeId)); + } + return pos; + }, + + /** + * Returns {from, to} position of a link. + */ + getLinkPosition: function (link) { + var from = this.getNodePosition(link.fromId), + to = this.getNodePosition(link.toId); + + return { + from : from, + to : to + }; + }, + + /** + * Sets position of a node to a given coordinates + */ + setNodePosition: function (node, x, y) { + var pos = layoutNodes[node.id]; + if (pos) { + pos.x = x; + pos.y = y; + } + }, + + // Layout specific methods: + + /** + * Based on argument either update default node placement callback or + * attempts to place given node using current placement callback. + * Setting new node callback triggers position update for all nodes. + * + * @param {Object} newPlaceNodeCallbackOrNode - if it is a function then + * default node placement callback is replaced with new one. Node placement + * callback has a form of function (node) {}, and is expected to return an + * object with x and y properties set to numbers. + * + * Otherwise if it's not a function the argument is treated as graph node + * and current node placement callback will be used to place it. + */ + placeNode : function (newPlaceNodeCallbackOrNode) { + if (typeof newPlaceNodeCallbackOrNode === 'function') { + placeNodeCallback = newPlaceNodeCallbackOrNode; + updateNodePositions(); + return this; + } + + // it is not a request to update placeNodeCallback, trying to place + // a node using current callback: + return placeNodeCallback(newPlaceNodeCallbackOrNode); + } + + }; +}; +/** + * @fileOverview Defines a graph renderer that uses CSS based drawings. + * + * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + */ - settings = Viva.lazyExtend(settings, { - /** - * Ideal length for links (springs in physical model). - */ - springLength: 80, +Viva.Graph.View = Viva.Graph.View || {}; - /** - * Hook's law coefficient. 1 - solid spring. - */ - springCoeff: 0.0002, +/** + * This is heart of the rendering. Class accepts graph to be rendered and rendering settings. + * It monitors graph changes and depicts them accordingly. + * + * @param graph - Viva.Graph.graph() object to be rendered. + * @param settings - rendering settings, composed from the following parts (with their defaults shown): + * settings = { + * // Represents a module that is capable of displaying graph nodes and links. + * // all graphics has to correspond to defined interface and can be later easily + * // replaced for specific needs (e.g. adding WebGL should be piece of cake as long + * // as WebGL has implemented required interface). See svgGraphics for example. + * // NOTE: current version supports Viva.Graph.View.cssGraphics() as well. + * graphics : Viva.Graph.View.svgGraphics(), + * + * // Where the renderer should draw graph. Container size matters, because + * // renderer will attempt center graph to that size. Also graphics modules + * // might depend on it. + * container : document.body, + * + * // Defines whether graph can respond to use input + * interactive: true, + * + * // Layout algorithm to be used. The algorithm is expected to comply with defined + * // interface and is expected to be iterative. Renderer will use it then to calculate + * // grpaph's layout. For examples of the interface refer to Viva.Graph.Layout.forceDirected() + * layout : Viva.Graph.Layout.forceDirected(), + * + * // Directs renderer to display links. Usually rendering links is the slowest part of this + * // library. So if you don't need to display links, consider settings this property to false. + * renderLinks : true, + * + * // Number of layout iterations to run before displaying the graph. The bigger you set this number + * // the closer to ideal position graph will apper first time. But be careful: for large graphs + * // it can freeze the browser. + * prerender : 0 + * } + */ +Viva.Graph.View.renderer = function (graph, settings) { + // TODO: This class is getting hard to understand. Consider refactoring. + // TODO: I have a technical debt here: fix scaling/recentring! Currently it's total mess. + var FRAME_INTERVAL = 30; - /** - * Coulomb's law coefficient. It's used to repel nodes thus should be negative - * if you make it positive nodes start attract each other :). - */ - gravity: -1.2, + settings = settings || {}; - /** - * Theta coeffiecient from Barnes Hut simulation. Ranged between (0, 1). - * The closer it's to 1 the more nodes algorithm will have to go through. - * Setting it to one makes Barnes Hut simulation no different from - * brute-force forces calculation (each node is considered). - */ - theta: 0.8, + var layout = settings.layout, + graphics = settings.graphics, + container = settings.container, + interactive = settings.interactive !== undefined ? settings.interactive : true, + inputManager, + animationTimer, + rendererInitialized = false, + updateCenterRequired = true, - /** - * Drag force coefficient. Used to slow down system, thus should be less than 1. - * The closer it is to 0 the less tight system will be. - */ - dragCoeff: 0.02, + currentStep = 0, + totalIterationsCount = 0, + isStable = false, + userInteraction = false, + isPaused = false, - /** - * Allows to transfor physical spring associated with a link. this allows clients - * to specify custom length for a link. - * - * @param {Viva.Graph.Link} link actual link for which transform is performed - * @param {Viva.Graph.Physics.Spring} spring physical spring which is associated with - * a link. Most interesting property will be 'length' - * - * @example - * // Let's say your graph represent friendship. Each link has associated - * // 'strength' of connection, distributed from 0 (not a strong connection) to - * // 1 (very strong connection) - * // - * // You want your graph to have uniformly distributed links, but stronger - * // connection should pull nodes closer: - * - * graph.addLink(user1, user2, { friendshipStrength: 0.9 }); - * var layout = Viva.Graph.Layout.forceDirected(graph, { - * springLength: 80, // 80 pixels is our ideal link length - * springTransform: function (link, spring) { - * // We can set custom desired length of a spring, based on - * // link's data: - * spring.length = 80 * (1 - link.data.friendshipStrength); - * } - * } - */ - springTransform: function (link, spring) { - // By default, it is a no-op + viewPortOffset = { + x : 0, + y : 0 }, - /** - * Default time step (dt) for forces integration - */ - timeStep : 20, + transform = { + offsetX : 0, + offsetY : 0, + scale : 1 + }; - /** - * Maximum movement of the system which can be considered as stabilized - */ - stableThreshold: 0.001 - }); + var prepareSettings = function () { + container = container || window.document.body; + layout = layout || Viva.Graph.Layout.forceDirected(graph); + graphics = graphics || Viva.Graph.View.svgGraphics(graph, {container : container}); - var forceSimulator = Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()), - nbodyForce = Viva.Graph.Physics.nbodyForce({ - gravity: settings.gravity, - theta: settings.theta - }), - springForce = Viva.Graph.Physics.springForce({ - length: settings.springLength, - coeff: settings.springCoeff - }), - dragForce = Viva.Graph.Physics.dragForce({ - coeff: settings.dragCoeff - }), - graphRect = new Viva.Graph.Rect(), - random = Viva.random('ted.com', 103, 114, 101, 97, 116), - - nodeBodies = {}, - getBestNodePosition = function(node) { - // TODO: Initial position could be picked better, e.g. take into - // account all neighbouring nodes/links, not only one. - // How about center of mass? - if (node.position) { - return node.position; - } - var baseX = (graphRect.x1 + graphRect.x2) / 2, - baseY = (graphRect.y1 + graphRect.y2) / 2, - springLength = settings.springLength; - - if (node.links && node.links.length > 0) { - var firstLink = node.links[0], - otherNode = firstLink.fromId !== node.id ? nodeBodies[firstLink.fromId] : nodeBodies[firstLink.toId]; - if (otherNode && otherNode.location) { - baseX = otherNode.location.x; - baseY = otherNode.location.y; - } + if (!settings.hasOwnProperty('renderLinks')) { + settings.renderLinks = true; } - return { - x: baseX + random.next(springLength) - springLength / 2, - y: baseY + random.next(springLength) - springLength / 2 - }; - }, - - getBody = function (nodeId) { - return nodeBodies[nodeId]; - }, - - releaseBody = function (nodeId) { - nodeBodies[nodeId] = null; - delete nodeBodies[nodeId]; + settings.prerender = settings.prerender || 0; + inputManager = (graphics.inputManager || Viva.Input.domInputManager)(graph, graphics); }, + windowEvents = Viva.Graph.Utils.events(window), + publicEvents = Viva.Graph.Utils.events({}).extend(), + graphEvents, + containerDrag, - springs = {}, + renderGraph = function () { + graphics.beginRender(); - updateBodyMass = function(nodeId) { - var body = getBody(nodeId); - body.mass = 1 + graph.getLinks(nodeId).length / 3.0; + // todo: move this check graphics + if (settings.renderLinks) { + graphics.renderLinks(); + } + graphics.renderNodes(); + graphics.endRender(); }, - isNodePinned = function(node) { - return (node && (node.isPinned || (node.data && node.data.isPinned))); - }, + onRenderFrame = function () { + isStable = layout.step() && !userInteraction; + renderGraph(); - isBodyPinned = function (body) { - return body.isPinned; + return !isStable; }, - initNode = function(nodeId) { - var body = getBody(nodeId); - if (!body) { - var node = graph.getNode(nodeId); - if (!node) { - return; // what are you doing? - } + renderIterations = function (iterationsCount) { + if (animationTimer) { + totalIterationsCount += iterationsCount; + return; + } - body = new Viva.Graph.Physics.Body(); - nodeBodies[nodeId] = body; - var position = getBestNodePosition(node); - body.loc(position); - updateBodyMass(nodeId); + if (iterationsCount) { + totalIterationsCount += iterationsCount; - if (isNodePinned(node)) { - body.isPinned = true; - } - forceSimulator.addBody(body); + animationTimer = Viva.Graph.Utils.timer(function () { + return onRenderFrame(); + }, FRAME_INTERVAL); + } else { + currentStep = 0; + totalIterationsCount = 0; + animationTimer = Viva.Graph.Utils.timer(onRenderFrame, FRAME_INTERVAL); } }, - initNodeObject = function (node) { - initNode(node.id); - }, + resetStable = function () { + if(isPaused) { + return; + } - releaseNode = function(node) { - var body = getBody(node.id); - if (body) { - releaseBody(node.id); + isStable = false; + animationTimer.restart(); + }, - forceSimulator.removeBody(body); - if (graph.getNodesCount() === 0) { - graphRect.x1 = graphRect.y1 = 0; - graphRect.x2 = graphRect.y2 = 0; + prerender = function () { + // To get good initial positions for the graph + // perform several prerender steps in background. + var i; + if (typeof settings.prerender === 'number' && settings.prerender > 0) { + for (i = 0; i < settings.prerender; i += 1) { + layout.step(); } } }, - initLink = function(link) { - updateBodyMass(link.fromId); - updateBodyMass(link.toId); + updateCenter = function () { + var graphRect = layout.getGraphRect(), + containerSize = Viva.Graph.Utils.getDimension(container); - var fromBody = getBody(link.fromId), - toBody = getBody(link.toId), - spring = forceSimulator.addSpring(fromBody, toBody, -1.0, link.weight); + viewPortOffset.x = viewPortOffset.y = 0; + transform.offsetX = containerSize.width / 2 - (graphRect.x2 + graphRect.x1) / 2; + transform.offsetY = containerSize.height / 2 - (graphRect.y2 + graphRect.y1) / 2; + graphics.graphCenterChanged(transform.offsetX, transform.offsetY); - settings.springTransform(link, spring); - springs[link.id] = spring; + updateCenterRequired = false; }, - releaseLink = function(link) { - var spring = springs[link.id]; - if (spring) { - var from = graph.getNode(link.fromId), - to = graph.getNode(link.toId); - if (from) { - updateBodyMass(from.id); - } - if (to) { - updateBodyMass(to.id); - } - delete springs[link.id]; - - forceSimulator.removeSpring(spring); - } + createNodeUi = function (node) { + var nodePosition = layout.getNodePosition(node.id); + graphics.addNode(node, nodePosition); }, - onGraphChanged = function(changes) { - for (var i = 0; i < changes.length; ++i) { - var change = changes[i]; - if (change.changeType === 'add') { - if (change.node) { - initNode(change.node.id); - } - if (change.link) { - initLink(change.link); - } - } else if (change.changeType === 'remove') { - if (change.node) { - releaseNode(change.node); - } - if (change.link) { - releaseLink(change.link); - } - } - } + removeNodeUi = function (node) { + graphics.releaseNode(node); }, - initSimulator = function() { - graph.forEachNode(initNodeObject); - graph.forEachLink(initLink); - graph.addEventListener('changed', onGraphChanged); + createLinkUi = function (link) { + var linkPosition = layout.getLinkPosition(link); + graphics.addLink(link, linkPosition); }, - updateNodePositions = function() { - var x1 = Number.MAX_VALUE, - y1 = Number.MAX_VALUE, - x2 = Number.MIN_VALUE, - y2 = Number.MIN_VALUE; + removeLinkUi = function (link) { + graphics.releaseLink(link); + }, - if (graph.getNodesCount() === 0) { + listenNodeEvents = function (node) { + var wasPinned = false; + var nodeInteractive = (typeof interactive === 'string' && interactive.indexOf('node') !== -1) || interactive; + if (!nodeInteractive) { return; } - for (var key in nodeBodies) { - if (nodeBodies.hasOwnProperty(key)) { - // how about pinned nodes? - var body = nodeBodies[key]; - if (isBodyPinned(body)) { - body.location.x = body.prevLocation.x; - body.location.y = body.prevLocation.y; - } else { - body.prevLocation.x = body.location.x; - body.prevLocation.y = body.location.y; - } - if (body.location.x < x1) { - x1 = body.location.x; - } - if (body.location.x > x2) { - x2 = body.location.x; - } - if (body.location.y < y1) { - y1 = body.location.y; - } - if (body.location.y > y2) { - y2 = body.location.y; - } - } - } - - graphRect.x1 = x1; - graphRect.x2 = x2; - graphRect.y1 = y1; - graphRect.y2 = y2; - }; - forceSimulator.setSpringForce(springForce); - forceSimulator.setNbodyForce(nbodyForce); - forceSimulator.setDragForce(dragForce); + // TODO: This may not be memory efficient. Consider reusing handlers object. + inputManager.bindDragNDrop(node, { + onStart : function () { + wasPinned = layout.isNodePinned(node); + layout.pinNode(node, true); + userInteraction = true; + resetStable(); + }, + onDrag : function (e, offset) { + var oldPos = layout.getNodePosition(node.id); + layout.setNodePosition(node, + oldPos.x + offset.x / transform.scale, + oldPos.y + offset.y / transform.scale); - initSimulator(); + userInteraction = true; - return { - /** - * Attempts to layout graph within given number of iterations. - * - * @param {integer} [iterationsCount] number of algorithm's iterations. - */ - run: function(iterationsCount) { - var i; - iterationsCount = iterationsCount || 50; + renderGraph(); + }, + onStop : function () { + layout.pinNode(node, wasPinned); + userInteraction = false; + } + }); + }, - for (i = 0; i < iterationsCount; ++i) { - this.step(); - } + releaseNodeEvents = function (node) { + inputManager.bindDragNDrop(node, null); }, - /** - * Performs one step of iterative layout algorithm - */ - step: function() { - var energy = forceSimulator.run(settings.timeStep); - updateNodePositions(); + initDom = function () { + graphics.init(container); - return energy < settings.stableThreshold; - }, + graph.forEachNode(createNodeUi); - /* - * Checks whether given node is pinned; - */ - isNodePinned: function (node) { - var body = getBody(node.id); - if (body) { - return isBodyPinned(body); + if (settings.renderLinks) { + graph.forEachLink(createLinkUi); } }, - /* - * Requests layout algorithm to pin/unpin node to its current position - * Pinned nodes should not be affected by layout algorithm and always - * remain at their position - */ - pinNode: function (node, isPinned) { - var body = getBody(node.id); - body.isPinned = !!isPinned; + releaseDom = function () { + graphics.release(container); }, - /* - * Gets position of a node by its id. If node was not seen by this - * layout algorithm undefined value is returned; - */ - getNodePosition: function (nodeId) { - var body = getBody(nodeId); - if (!body) { - initNode(nodeId); - body = getBody(nodeId); - } - return body && body.location; - }, + processNodeChange = function (change) { + var node = change.node; - /** - * Returns {from, to} position of a link. - */ - getLinkPosition: function (link) { - var from = this.getNodePosition(link.fromId), - to = this.getNodePosition(link.toId); + if (change.changeType === 'add') { + createNodeUi(node); + listenNodeEvents(node); + if (updateCenterRequired) { + updateCenter(); + } + } else if (change.changeType === 'remove') { + releaseNodeEvents(node); + removeNodeUi(node); + if (graph.getNodesCount() === 0) { + updateCenterRequired = true; // Next time when node is added - center the graph. + } + } else if (change.changeType === 'update') { + releaseNodeEvents(node); + removeNodeUi(node); - return { - from : from, - to : to - }; + createNodeUi(node); + listenNodeEvents(node); + } }, - /** - * Sets position of a node to a given coordinates - */ - setNodePosition: function (node, x, y) { - var body = getBody(node.id); - if (body) { - body.prevLocation.x = body.location.x = x; - body.prevLocation.y = body.location.y = y; + processLinkChange = function (change) { + var link = change.link; + if (change.changeType === 'add') { + if (settings.renderLinks) { createLinkUi(link); } + } else if (change.changeType === 'remove') { + if (settings.renderLinks) { removeLinkUi(link); } + } else if (change.changeType === 'update') { + throw 'Update type is not implemented. TODO: Implement me!'; } }, - /** - * Returns rectangle structure {x1, y1, x2, y2}, which represents - * current space occupied by graph. - */ - getGraphRect: function() { - return graphRect; + onGraphChanged = function (changes) { + var i, change; + for (i = 0; i < changes.length; i += 1) { + change = changes[i]; + if (change.node) { + processNodeChange(change); + } else if (change.link) { + processLinkChange(change); + } + } + + resetStable(); }, - /** - * Request to release all resources - */ - dispose: function() { - graph.removeEventListener('change', onGraphChanged); + onWindowResized = function () { + updateCenter(); + onRenderFrame(); }, - // Layout specific methods - /** - * Gets or sets current desired length of the edge. - * - * @param length new desired length of the springs (aka edge, aka link). - * if this parameter is empty then old spring length is returned. - */ - springLength: function(length) { - if (arguments.length === 1) { - springForce.options({ - length: length - }); - return this; + releaseContainerDragManager = function () { + if (containerDrag) { + containerDrag.release(); + containerDrag = null; } - - return springForce.options().length; }, - /** - * Gets or sets current spring coeffiсient. - * - * @param coeff new spring coeffiсient. - * if this parameter is empty then its old value returned. - */ - springCoeff: function(coeff) { - if (arguments.length === 1) { - springForce.options({ - coeff: coeff - }); - return this; + releaseGraphEvents = function () { + if (graphEvents) { + // Interesting.. why is it not null? Anyway: + graphEvents.stop('changed', onGraphChanged); + graphEvents = null; } - - return springForce.options().coeff; }, - /** - * Gets or sets current gravity in the nbody simulation. - * - * @param g new gravity constant. - * if this parameter is empty then its old value returned. - */ - gravity: function(g) { - if (arguments.length === 1) { - nbodyForce.options({ - gravity: g - }); - return this; + scale = function (out, scrollPoint) { + if (!scrollPoint) { + var containerSize = Viva.Graph.Utils.getDimension(container); + scrollPoint = { + x: containerSize.width/2, + y: containerSize.height/2 + }; } + var scaleFactor = Math.pow(1 + 0.4, out ? -0.2 : 0.2); + transform.scale = graphics.scale(scaleFactor, scrollPoint); + + renderGraph(); + publicEvents.fire('scale', transform.scale); - return nbodyForce.options().gravity; + return transform.scale; }, - /** - * Gets or sets current theta value in the nbody simulation. - * - * @param t new theta coeffiсient. - * if this parameter is empty then its old value returned. - */ - theta: function(t) { - if (arguments.length === 1) { - nbodyForce.options({ - theta: t - }); - return this; - } + listenToEvents = function () { + windowEvents.on('resize', onWindowResized); - return nbodyForce.options().theta; - }, + releaseContainerDragManager(); + var canDrag = (typeof interactive === 'string' && interactive.indexOf('drag') !== -1) || interactive; + if (canDrag) { + containerDrag = Viva.Graph.Utils.dragndrop(container); + containerDrag.onDrag(function (e, offset) { + viewPortOffset.x += offset.x; + viewPortOffset.y += offset.y; + graphics.translateRel(offset.x, offset.y); - /** - * Gets or sets current theta value in the nbody simulation. - * - * @param dragCoeff new drag coeffiсient. - * if this parameter is empty then its old value returned. - */ - drag: function(dragCoeff) { - if (arguments.length === 1) { - dragForce.options({ - coeff: dragCoeff + renderGraph(); }); - return this; } - return dragForce.options().coeff; - } - }; -}; -Viva.Graph.Layout = Viva.Graph.Layout || {}; - -/** - * Does not really perform any layouting algorithm but is compliant - * with renderer interface. Allowing clients to provide specific positioning - * callback and get static layout of the graph - * - * @param {Viva.Graph.graph} graph to layout - * @param {Object} userSettings - */ -Viva.Graph.Layout.constant = function (graph, userSettings) { - userSettings = Viva.lazyExtend(userSettings, { - maxX : 1024, - maxY : 1024, - seed : 'Deterministic randomness made me do this' - }); - // This class simply follows API, it does not use some of the arguments: - /*jshint unused: false */ - var rand = Viva.random(userSettings.seed), - graphRect = new Viva.Graph.Rect(Number.MAX_VALUE, Number.MAX_VALUE, Number.MIN_VALUE, Number.MIN_VALUE), - - placeNodeCallback = function (node) { - return new Viva.Graph.Point2d(rand.next(userSettings.maxX), rand.next(userSettings.maxY)); - }, - - updateGraphRect = function (position, graphRect) { - if (position.x < graphRect.x1) { graphRect.x1 = position.x; } - if (position.x > graphRect.x2) { graphRect.x2 = position.x; } - if (position.y < graphRect.y1) { graphRect.y1 = position.y; } - if (position.y > graphRect.y2) { graphRect.y2 = position.y; } - }, + var canScroll = (typeof interactive === 'string' && interactive.indexOf('scroll') !== -1) || interactive; + if (canScroll) { + containerDrag.onScroll(function (e, scaleOffset, scrollPoint) { + scale(scaleOffset < 0, scrollPoint); + }); + } - layoutNodes = typeof Object.create === 'function' ? Object.create(null) : {}, + graph.forEachNode(listenNodeEvents); - ensureNodeInitialized = function (node) { - if (!node) { return; } - layoutNodes[node.id] = placeNodeCallback(node); - updateGraphRect(layoutNodes[node.id], graphRect); + releaseGraphEvents(); + graphEvents = Viva.Graph.Utils.events(graph); + graphEvents.on('changed', onGraphChanged); }, - updateNodePositions = function () { - if (graph.getNodesCount() === 0) { return; } + stopListenToEvents = function () { + rendererInitialized = false; + releaseGraphEvents(); + releaseContainerDragManager(); + windowEvents.stop('resize', onWindowResized); + publicEvents.removeAllListeners(); + animationTimer.stop(); - graphRect.x1 = Number.MAX_VALUE; - graphRect.y1 = Number.MAX_VALUE; - graphRect.x2 = Number.MIN_VALUE; - graphRect.y2 = Number.MIN_VALUE; + graph.forEachLink(function (link) { + if (settings.renderLinks) { removeLinkUi(link); } + }); - graph.forEachNode(ensureNodeInitialized); - }, + graph.forEachNode(function (node) { + releaseNodeEvents(node); + removeNodeUi(node); + }); - onGraphChanged = function(changes) { - for (var i = 0; i < changes.length; ++i) { - var change = changes[i]; - if (change.node) { - if (change.changeType === 'add') { - ensureNodeInitialized(change.node); - } else { - delete layoutNodes[change.node.id]; - } - } - } + layout.dispose(); + releaseDom(); }; - graph.addEventListener('changed', onGraphChanged); - return { /** - * Attempts to layout graph within given number of iterations. + * Performs rendering of the graph. + * + * @param iterationsCount if specified renderer will run only given number of iterations + * and then stop. Otherwise graph rendering is performed infinitely. * - * @param {integer} [iterationsCount] number of algorithm's iterations. - * The constant layout ignores this parameter. + * Note: if rendering stopped by used started dragging nodes or new nodes were added to the + * graph renderer will give run more iterations to reflect changes. */ run : function (iterationsCount) { - this.step(); - }, - /** - * One step of layout algorithm. - */ - step : function () { - updateNodePositions(); + if (!rendererInitialized) { + prepareSettings(); + prerender(); - return true; // no need to continue. - }, + updateCenter(); + initDom(); + listenToEvents(); - /** - * Returns rectangle structure {x1, y1, x2, y2}, which represents - * current space occupied by graph. - */ - getGraphRect : function () { - return graphRect; - }, + rendererInitialized = true; + } - /** - * Request to release all resources - */ - dispose : function () { - graph.removeEventListener('change', onGraphChanged); + renderIterations(iterationsCount); + + return this; }, - /* - * Checks whether given node is pinned; all nodes in this layout are pinned. - */ - isNodePinned: function (node) { - return true; + reset : function () { + graphics.resetScale(); + updateCenter(); + transform.scale = 1; }, - /* - * Requests layout algorithm to pin/unpin node to its current position - * Pinned nodes should not be affected by layout algorithm and always - * remain at their position - */ - pinNode: function (node, isPinned) { - // noop + pause : function () { + isPaused = true; + animationTimer.stop(); }, - /* - * Gets position of a node by its id. If node was not seen by this - * layout algorithm undefined value is returned; - */ - getNodePosition: function (nodeId) { - var pos = layoutNodes[nodeId]; - if (!pos) { - ensureNodeInitialized(graph.getNode(nodeId)); - } - return pos; + resume : function () { + isPaused = false; + animationTimer.restart(); }, - /** - * Returns {from, to} position of a link. - */ - getLinkPosition: function (link) { - var from = this.getNodePosition(link.fromId), - to = this.getNodePosition(link.toId); + rerender : function () { + renderGraph(); + return this; + }, - return { - from : from, - to : to - }; + zoomOut: function () { + return scale(true); + }, + + zoomIn: function () { + return scale(false); }, /** - * Sets position of a node to a given coordinates + * Centers renderer at x,y graph's coordinates */ - setNodePosition: function (node, x, y) { - var pos = layoutNodes[node.id]; - if (pos) { - pos.x = x; - pos.y = y; - } + moveTo: function (x, y) { + graphics.graphCenterChanged(transform.offsetX - x * transform.scale, transform.offsetY - y * transform.scale); + renderGraph(); }, - // Layout specific methods: + /** + * Gets current graphics object + */ + getGraphics: function () { + return graphics; + }, /** - * Based on argument either update default node placement callback or - * attempts to place given node using current placement callback. - * Setting new node callback triggers position update for all nodes. - * - * @param {Object} newPlaceNodeCallbackOrNode - if it is a function then - * default node placement callback is replaced with new one. Node placement - * callback has a form of function (node) {}, and is expected to return an - * object with x and y properties set to numbers. - * - * Otherwise if it's not a function the argument is treated as graph node - * and current node placement callback will be used to place it. + * Removes this renderer and deallocates all resources/timers */ - placeNode : function (newPlaceNodeCallbackOrNode) { - if (typeof newPlaceNodeCallbackOrNode === 'function') { - placeNodeCallback = newPlaceNodeCallbackOrNode; - updateNodePositions(); - return this; - } + dispose : function () { + stopListenToEvents(); // I quit! + }, - // it is not a request to update placeNodeCallback, trying to place - // a node using current callback: - return placeNodeCallback(newPlaceNodeCallbackOrNode); - } + on : function (eventName, callback) { + publicEvents.addEventListener(eventName, callback); + return this; + }, + off : function (eventName, callback) { + publicEvents.removeEventListener(eventName, callback); + return this; + } }; }; -/** - * @fileOverview Defines a graph renderer that uses CSS based drawings. +Viva.Graph.serializer = function () { + var checkJSON = function () { + if (typeof JSON === 'undefined' || !JSON.stringify || !JSON.parse) { + throw 'JSON serializer is not defined.'; + } + }, + + nodeTransformStore = function (node) { + return { id : node.id, data: node.data }; + }, + + linkTransformStore = function (link) { + return { + fromId : link.fromId, + toId: link.toId, + data : link.data + }; + }, + + nodeTransformLoad = function (node) { + return node; + }, + + linkTransformLoad = function (link) { + return link; + }; + + return { + /** + * Saves graph to JSON format. + * + * NOTE: ECMAScript 5 (or alike) JSON object is required to be defined + * to get proper output. + * + * @param graph to be saved in JSON format. + * @param nodeTransform optional callback function(node) which returns what should be passed into nodes collection + * @param linkTransform optional callback functions(link) which returns what should be passed into the links collection + */ + storeToJSON : function (graph, nodeTransform, linkTransform) { + if (!graph) { throw 'Graph is not defined'; } + checkJSON(); + + nodeTransform = nodeTransform || nodeTransformStore; + linkTransform = linkTransform || linkTransformStore; + + var store = { + nodes : [], + links : [] + }; + + graph.forEachNode(function (node) { store.nodes.push(nodeTransform(node)); }); + graph.forEachLink(function (link) { store.links.push(linkTransform(link)); }); + + return JSON.stringify(store); + }, + + /** + * Restores graph from JSON string created by storeToJSON() method. + * + * NOTE: ECMAScript 5 (or alike) JSON object is required to be defined + * to get proper output. + * + * @param jsonString is a string produced by storeToJSON() method. + * @param nodeTransform optional callback function(node) which accepts deserialized node and returns object with + * 'id' and 'data' properties. + * @param linkTransform optional callback functions(link) which accepts deserialized link and returns link object with + * 'fromId', 'toId' and 'data' properties. + */ + loadFromJSON : function (jsonString, nodeTransform, linkTransform) { + if (typeof jsonString !== 'string') { throw 'String expected in loadFromJSON() method'; } + checkJSON(); + + nodeTransform = nodeTransform || nodeTransformLoad; + linkTransform = linkTransform || linkTransformLoad; + + var store = JSON.parse(jsonString), + graph = Viva.Graph.graph(), + i; + + if (!store || !store.nodes || !store.links) { throw 'Passed json string does not represent valid graph'; } + + for (i = 0; i < store.nodes.length; ++i) { + var parsedNode = nodeTransform(store.nodes[i]); + if (!parsedNode.hasOwnProperty('id')) { throw 'Graph node format is invalid. Node.id is missing'; } + + graph.addNode(parsedNode.id, parsedNode.data); + } + + for (i = 0; i < store.links.length; ++i) { + var link = linkTransform(store.links[i]); + if (!link.hasOwnProperty('fromId') || !link.hasOwnProperty('toId')) { throw 'Graph link format is invalid. Both fromId and toId are required'; } + + graph.addLink(link.fromId, link.toId, link.data); + } + + return graph; + } + }; +}; +/** + * @fileOverview Centrality calcuation algorithms. + * + * @see http://en.wikipedia.org/wiki/Centrality + * + * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + */ + +Viva.Graph.centrality = function () { + var singleSourceShortestPath = function (graph, node, oriented) { + // I'm using the same naming convention used in http://www.inf.uni-konstanz.de/algo/publications/b-fabc-01.pdf + // sorry about cryptic names. + var P = {}, // predcessors lists. + S = [], + sigma = {}, + d = {}, + Q = [node.id], + v, + dV, + sigmaV, + processNode = function (w) { + // w found for the first time? + if (!d.hasOwnProperty(w.id)) { + Q.push(w.id); + d[w.id] = dV + 1; + } + // Shortest path to w via v? + if (d[w.id] === dV + 1) { + sigma[w.id] += sigmaV; + P[w.id].push(v); + } + }; + + graph.forEachNode(function (t) { + P[t.id] = []; + sigma[t.id] = 0; + }); + + d[node.id] = 0; + sigma[node.id] = 1; + + while (Q.length) { // Using BFS to find shortest paths + v = Q.shift(); + dV = d[v]; + sigmaV = sigma[v]; + + S.push(v); + graph.forEachLinkedNode(v, processNode, oriented); + } + + return { + S : S, + P : P, + sigma : sigma + }; + }, + + accumulate = function (betweenness, shortestPath, s) { + var delta = {}, + S = shortestPath.S, + i, + w, + coeff, + pW, + v; + + for (i = 0; i < S.length; i += 1) { + delta[S[i]] = 0; + } + + // S returns vertices in order of non-increasing distance from s + while (S.length) { + w = S.pop(); + coeff = (1 + delta[w]) / shortestPath.sigma[w]; + pW = shortestPath.P[w]; + + for (i = 0; i < pW.length; i += 1) { + v = pW[i]; + delta[v] += shortestPath.sigma[v] * coeff; + } + + if (w !== s) { + betweenness[w] += delta[w]; + } + } + }, + + sortBetweennes = function (b) { + var sorted = [], + key; + for (key in b) { + if (b.hasOwnProperty(key)) { + sorted.push({ key : key, value : b[key]}); + } + } + + return sorted.sort(function (x, y) { return y.value - x.value; }); + }; + + return { + + /** + * Compute the shortest-path betweenness centrality for all nodes in a graph. + * + * Betweenness centrality of a node `n` is the sum of the fraction of all-pairs + * shortest paths that pass through `n`. Runtime O(n * v) for non-weighted graphs. + * + * @see http://en.wikipedia.org/wiki/Centrality#Betweenness_centrality + * + * @see A Faster Algorithm for Betweenness Centrality. + * Ulrik Brandes, Journal of Mathematical Sociology 25(2):163-177, 2001. + * http://www.inf.uni-konstanz.de/algo/publications/b-fabc-01.pdf + * + * @see Ulrik Brandes: On Variants of Shortest-Path Betweenness + * Centrality and their Generic Computation. + * Social Networks 30(2):136-145, 2008. + * http://www.inf.uni-konstanz.de/algo/publications/b-vspbc-08.pdf + * + * @see Ulrik Brandes and Christian Pich: Centrality Estimation in Large Networks. + * International Journal of Bifurcation and Chaos 17(7):2303-2318, 2007. + * http://www.inf.uni-konstanz.de/algo/publications/bp-celn-06.pdf + * + * @param graph for which we are calculating betweenness centrality. Non-weighted graphs are only supported + */ + betweennessCentrality : function (graph) { + var betweennes = {}, + shortestPath; + graph.forEachNode(function (node) { + betweennes[node.id] = 0; + }); + + graph.forEachNode(function (node) { + shortestPath = singleSourceShortestPath(graph, node); + accumulate(betweennes, shortestPath, node); + }); + + return sortBetweennes(betweennes); + }, + + /** + * Calculates graph nodes degree centrality (in/out or both). + * + * @see http://en.wikipedia.org/wiki/Centrality#Degree_centrality + * + * @param graph for which we are calculating centrality. + * @param kind optional parameter. Valid values are + * 'in' - calculate in-degree centrality + * 'out' - calculate out-degree centrality + * - if it's not set generic degree centrality is calculated + */ + degreeCentrality : function (graph, kind) { + var calcDegFunction, + sortedDegrees = [], + result = [], + degree; + + kind = (kind || 'both').toLowerCase(); + if (kind === 'in') { + calcDegFunction = function (links, nodeId) { + var total = 0, + i; + for (i = 0; i < links.length; i += 1) { + total += (links[i].toId === nodeId) ? 1 : 0; + } + return total; + }; + } else if (kind === 'out') { + calcDegFunction = function (links, nodeId) { + var total = 0, + i; + for (i = 0; i < links.length; i += 1) { + total += (links[i].fromId === nodeId) ? 1 : 0; + } + return total; + }; + } else if (kind === 'both') { + calcDegFunction = function (links) { + return links.length; + }; + } else { + throw 'Expected centrality degree kind is: in, out or both'; + } + + graph.forEachNode(function (node) { + var links = graph.getLinks(node.id), + nodeDeg = calcDegFunction(links, node.id); + + if (!sortedDegrees.hasOwnProperty(nodeDeg)) { + sortedDegrees[nodeDeg] = [node.id]; + } else { + sortedDegrees[nodeDeg].push(node.id); + } + }); + + for (degree in sortedDegrees) { + if (sortedDegrees.hasOwnProperty(degree)) { + var nodes = sortedDegrees[degree], + j; + if (nodes) { + for (j = 0; j < nodes.length; ++j) { + result.unshift({key : nodes[j], value : parseInt(degree, 10)}); + } + } + } + } + + return result; + } + }; +};/** + * @fileOverview Community structure detection algorithms + * + * @see http://en.wikipedia.org/wiki/Community_structure + * + * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + */ + +Viva.Graph.community = function () { + return { + /** + * Implementation of Speaker-listener Label Propagation Algorithm (SLPA) of + * Jierui Xie and Boleslaw K. Szymanski. + * + * @see http://arxiv.org/pdf/1109.5720v3.pdf + * @see https://sites.google.com/site/communitydetectionslpa/ + */ + slpa : function (graph, T, r) { + var algorithm = Viva.Graph._community.slpaAlgorithm(graph, T, r); + return algorithm.run(); + } + }; +};Viva.Graph._community = {}; + +/** + * Implementation of Speaker-listener Label Propagation Algorithm (SLPA) of + * Jierui Xie and Boleslaw K. Szymanski. + * + * @see http://arxiv.org/pdf/1109.5720v3.pdf + * @see https://sites.google.com/site/communitydetectionslpa/ + */ +Viva.Graph._community.slpaAlgorithm = function (graph, T, r) { + T = T || 100; // number of evaluation iterations. Should be at least 20. Influence memory consumption by O(n * T); + r = r || 0.3; // community threshold on scale from 0 to 1. Value greater than 0.5 result in disjoint communities. + + var random = Viva.random(1331782216905), + shuffleRandom = Viva.random('Greeting goes to you, ', 'dear reader'), + + calculateCommunities = function (nodeMemory, threshold) { + var communities = []; + nodeMemory.forEachUniqueWord(function (word, count) { + if (count > threshold) { + communities.push({name : word, probability : count / T }); + } else { + return true; // stop enumeration, nothing more popular after this word. + } + }); + + return communities; + }, + + init = function (graph) { + var algoNodes = []; + graph.forEachNode(function (node) { + var memory = Viva.Graph._community.occuranceMap(random); + memory.add(node.id); + + node.slpa = { memory : memory }; + algoNodes.push(node.id); + }); + + return algoNodes; + }, + + evaluate = function (graph, nodes) { + var shuffle = Viva.randomIterator(nodes, shuffleRandom), + t, + + /** + * One iteration of SLPA. + */ + processNode = function (nodeId) { + var listner = graph.getNode(nodeId), + saidWords = Viva.Graph._community.occuranceMap(random); + + graph.forEachLinkedNode(nodeId, function (speakerNode) { + var word = speakerNode.slpa.memory.getRandomWord(); + saidWords.add(word); + }); + + // selecting the most popular label from what it observed in the current step + var heard = saidWords.getMostPopularFair(); + listner.slpa.memory.add(heard); + }; + + for (t = 0; t < T - 1; ++t) { // -1 is because one 'step' was during init phase + shuffle.forEach(processNode); + } + }, + + postProcess = function (graph) { + var communities = {}; + + graph.forEachNode(function (node) { + var nodeCommunities = calculateCommunities(node.slpa.memory, r * T), + i; + + for (i = 0; i < nodeCommunities.length; ++i) { + var communityName = nodeCommunities[i].name; + if (communities.hasOwnProperty(communityName)) { + communities[communityName].push(node.id); + } else { + communities[communityName] = [node.id]; + } + } + + node.communities = nodeCommunities; // TODO: I doesn't look right to augment node's properties. No? + + // Speaking of memory. Node memory created by slpa is really expensive. Release it: + node.slpa = null; + delete node.slpa; + }); + + return communities; + }; + + return { + + /** + * Executes SLPA algorithm. The function returns dictionary of discovered communities: + * { + * 'communityName1' : [nodeId1, nodeId2, .., nodeIdN], + * 'communityName2' : [nodeIdK1, nodeIdK2, .., nodeIdKN], + * ... + * }; + * + * After algorithm is done each node is also augmented with new property 'communities': + * + * node.communities = [ + * {name: 'communityName1', probability: 0.78}, + * {name: 'communityName2', probability: 0.63}, + * ... + * ]; + * + * 'probability' is always higher than 'r' parameter and denotes level of confidence + * with which we think node belongs to community. + * + * Runtime is O(T * m), where m is total number of edges, and T - number of algorithm iterations. + * + */ + run : function () { + var nodes = init(graph); + + evaluate(graph, nodes); + + return postProcess(graph); + } + }; +}; + +/** + * A data structure which serves as node memory during SLPA execution. The main idea is to + * simplify operations on memory such as + * - add word to memory, + * - get random word from memory, with probablity proportional to word occurrence in the memory + * - get the most popular word in memory + * + * TODO: currently this structure is extremely inefficient in terms of memory. I think it could be + * optimized. + */ +Viva.Graph._community.occuranceMap = function (random) { + random = random || Viva.random(); + + var wordsCount = {}, + allWords = [], + dirtyPopularity = false, + uniqueWords = [], + + rebuildPopularityArray = function () { + var key; + + uniqueWords.length = 0; + for (key in wordsCount) { + if (wordsCount.hasOwnProperty(key)) { + uniqueWords.push(key); + } + } + + uniqueWords.sort(function (x, y) { + var result = wordsCount[y] - wordsCount[x]; + if (result) { + return result; + } + + // Not only number of occurances matters but order of keys also does. + // for ... in implementation in different browsers results in different + // order, and if we want to have same categories accross all browsers + // we should order words by key names too: + if (x < y) { return -1; } + if (x > y) { return 1; } + + return 0; + }); + }, + + ensureUniqueWordsUpdated = function () { + if (dirtyPopularity) { + rebuildPopularityArray(); + dirtyPopularity = false; + } + }; + + return { + + /** + * Adds a new word to the collection of words. + */ + add : function (word) { + word = String(word); + if (wordsCount.hasOwnProperty(word)) { + wordsCount[word] += 1; + } else { + wordsCount[word] = 1; + } + + allWords.push(word); + dirtyPopularity = true; + }, + + /** + * Gets number of occurances for a given word. If word is not present in the dictionary + * zero is returned. + */ + getWordCount : function (word) { + return wordsCount[word] || 0; + }, + + /** + * Gets the most popular word in the map. If multiple words are at the same position + * random word among them is choosen. + * + */ + getMostPopularFair : function () { + if (allWords.length === 1) { + return allWords[0]; // optimizes speed for simple case. + } + + ensureUniqueWordsUpdated(); + + var maxCount = 0, + i; + + for (i = 1; i < uniqueWords.length; ++i) { + if (wordsCount[uniqueWords[i - 1]] !== wordsCount[uniqueWords[i]]) { + break; // other words are less popular... not interested. + } else { + maxCount += 1; + } + } + + maxCount += 1; // to include upper bound. i.e. random words between [0, maxCount] (not [0, maxCount) ). + return uniqueWords[random.next(maxCount)]; + }, + + /** + * Selects a random word from map with probability proportional + * to the occurrence frequency of words. + */ + getRandomWord : function () { + if (allWords.length === 0) { + throw 'The occurance map is empty. Cannot get empty word'; + } + + return allWords[random.next(allWords.length)]; + }, + + /** + * Enumerates all unique words in the map, and calls + * callback(word, occuranceCount) function on each word. Callback + * can return true value to stop enumeration. + * + * Note: enumeration is guaranteed in to run in decreasing order. + */ + forEachUniqueWord : function (callback) { + if (typeof callback !== 'function') { + throw 'Function callback is expected to enumerate all words'; + } + var i; + + ensureUniqueWordsUpdated(); + + for (i = 0; i < uniqueWords.length; ++i) { + var word = uniqueWords[i], + count = wordsCount[word]; + + var stop = callback(word, count); + if (stop) { + break; + } + } + } + }; +};/** + * @fileOverview Contains collection of graph generators. * * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com */ -Viva.Graph.View = Viva.Graph.View || {}; +Viva.Graph.generator = function () { -/** - * This is heart of the rendering. Class accepts graph to be rendered and rendering settings. - * It monitors graph changes and depicts them accordingly. - * - * @param graph - Viva.Graph.graph() object to be rendered. - * @param settings - rendering settings, composed from the following parts (with their defaults shown): - * settings = { - * // Represents a module that is capable of displaying graph nodes and links. - * // all graphics has to correspond to defined interface and can be later easily - * // replaced for specific needs (e.g. adding WebGL should be piece of cake as long - * // as WebGL has implemented required interface). See svgGraphics for example. - * // NOTE: current version supports Viva.Graph.View.cssGraphics() as well. - * graphics : Viva.Graph.View.svgGraphics(), - * - * // Where the renderer should draw graph. Container size matters, because - * // renderer will attempt center graph to that size. Also graphics modules - * // might depend on it. - * container : document.body, - * - * // Defines whether graph can respond to use input - * interactive: true, - * - * // Layout algorithm to be used. The algorithm is expected to comply with defined - * // interface and is expected to be iterative. Renderer will use it then to calculate - * // grpaph's layout. For examples of the interface refer to Viva.Graph.Layout.forceDirected() - * layout : Viva.Graph.Layout.forceDirected(), - * - * // Directs renderer to display links. Usually rendering links is the slowest part of this - * // library. So if you don't need to display links, consider settings this property to false. - * renderLinks : true, - * - * // Number of layout iterations to run before displaying the graph. The bigger you set this number - * // the closer to ideal position graph will apper first time. But be careful: for large graphs - * // it can freeze the browser. - * prerender : 0 - * } - */ -Viva.Graph.View.renderer = function (graph, settings) { - // TODO: This class is getting hard to understand. Consider refactoring. - // TODO: I have a technical debt here: fix scaling/recentring! Currently it's total mess. - var FRAME_INTERVAL = 30; + return { + /** + * Generates complete graph Kn. + * + * @param n represents number of nodes in the complete graph. + */ + complete : function (n) { + if (!n || n < 1) { + throw { message: "At least two nodes expected for complete graph" }; + } - settings = settings || {}; + var g = Viva.Graph.graph(), + i, + j; - var layout = settings.layout, - graphics = settings.graphics, - container = settings.container, - interactive = settings.interactive !== undefined ? settings.interactive : true, - inputManager, - animationTimer, - rendererInitialized = false, - updateCenterRequired = true, + g.Name = "Complete K" + n; - currentStep = 0, - totalIterationsCount = 0, - isStable = false, - userInteraction = false, - isPaused = false, + for (i = 0; i < n; ++i) { + for (j = i + 1; j < n; ++j) { + if (i !== j) { + g.addLink(i, j); + } + } + } - viewPortOffset = { - x : 0, - y : 0 + return g; }, - transform = { - offsetX : 0, - offsetY : 0, - scale : 1 - }; + /** + * Generates complete bipartite graph K n,m. Each node in the + * first partition is connected to all nodes in the second partition. + * + * @param n represents number of nodes in the first graph partition + * @param m represents number of nodes in the second graph partition + */ + completeBipartite : function (n, m) { + if (!n || !m || n < 0 || m < 0) { + throw { message: "Graph dimensions are invalid. Number of nodes in each partition should be greate than 0" }; + } - var prepareSettings = function () { - container = container || window.document.body; - layout = layout || Viva.Graph.Layout.forceDirected(graph); - graphics = graphics || Viva.Graph.View.svgGraphics(graph, {container : container}); + var g = Viva.Graph.graph(), + i, + j; - if (!settings.hasOwnProperty('renderLinks')) { - settings.renderLinks = true; + g.Name = "Complete K " + n + "," + m; + for (i = 0; i < n; ++i) { + for (j = n; j < n + m; ++j) { + g.addLink(i, j); + } } - settings.prerender = settings.prerender || 0; - inputManager = (graphics.inputManager || Viva.Input.domInputManager)(graph, graphics); + return g; }, - windowEvents = Viva.Graph.Utils.events(window), - publicEvents = Viva.Graph.Utils.events({}).extend(), - graphEvents, - containerDrag, + /** + * Generates a graph in a form of a ladder with n steps. + * + * @param n number of steps in the ladder. + */ + ladder : function (n) { + if (!n || n < 0) { + throw { message: "Invalid number of nodes" }; + } - renderGraph = function () { - graphics.beginRender(); + var g = Viva.Graph.graph(), + i; + g.Name = "Ladder graph " + n; - // todo: move this check graphics - if (settings.renderLinks) { - graphics.renderLinks(); + for (i = 0; i < n - 1; ++i) { + g.addLink(i, i + 1); + // first row + g.addLink(n + i, n + i + 1); + // second row + g.addLink(i, n + i); + // ladder"s step } - graphics.renderNodes(); - graphics.endRender(); - }, - onRenderFrame = function () { - isStable = layout.step() && !userInteraction; - renderGraph(); + g.addLink(n - 1, 2 * n - 1); + // last step in the ladder; - return !isStable; + return g; }, - renderIterations = function (iterationsCount) { - if (animationTimer) { - totalIterationsCount += iterationsCount; - return; + /** + * Generates a graph in a form of a circular ladder with n steps. + * + * @param n number of steps in the ladder. + */ + circularLadder : function (n) { + if (!n || n < 0) { + throw { message: "Invalid number of nodes" }; } - if (iterationsCount) { - totalIterationsCount += iterationsCount; + var g = this.ladder(n); + g.Name = "Circular ladder graph " + n; - animationTimer = Viva.Graph.Utils.timer(function () { - return onRenderFrame(); - }, FRAME_INTERVAL); - } else { - currentStep = 0; - totalIterationsCount = 0; - animationTimer = Viva.Graph.Utils.timer(onRenderFrame, FRAME_INTERVAL); + g.addLink(0, n - 1); + g.addLink(n, 2 * n - 1); + return g; + }, + /** + * Generates a graph in a form of a grid with n rows and m columns. + * + * @param n number of rows in the graph. + * @param m number of columns in the graph. + */ + grid: function (n, m) { + var g = Viva.Graph.graph(), + i, + j; + g.Name = "Grid graph " + n + "x" + m; + for (i = 0; i < n; ++i) { + for (j = 0; j < m; ++j) { + var node = i + j * n; + if (i > 0) { g.addLink(node, i - 1 + j * n); } + if (j > 0) { g.addLink(node, i + (j - 1) * n); } + } } + + return g; }, - resetStable = function () { - if(isPaused) { - return; + path: function (n) { + if (!n || n < 0) { + throw { message: "Invalid number of nodes" }; } - isStable = false; - animationTimer.restart(); - }, + var g = Viva.Graph.graph(), + i; + g.Name = "Path graph " + n; + g.addNode(0); - prerender = function () { - // To get good initial positions for the graph - // perform several prerender steps in background. - var i; - if (typeof settings.prerender === 'number' && settings.prerender > 0) { - for (i = 0; i < settings.prerender; i += 1) { - layout.step(); - } - } - }, - - updateCenter = function () { - var graphRect = layout.getGraphRect(), - containerSize = Viva.Graph.Utils.getDimension(container); - - viewPortOffset.x = viewPortOffset.y = 0; - transform.offsetX = containerSize.width / 2 - (graphRect.x2 + graphRect.x1) / 2; - transform.offsetY = containerSize.height / 2 - (graphRect.y2 + graphRect.y1) / 2; - graphics.graphCenterChanged(transform.offsetX, transform.offsetY); - - updateCenterRequired = false; - }, - - createNodeUi = function (node) { - var nodePosition = layout.getNodePosition(node.id); - graphics.addNode(node, nodePosition); - }, - - removeNodeUi = function (node) { - graphics.releaseNode(node); - }, - - createLinkUi = function (link) { - var linkPosition = layout.getLinkPosition(link); - graphics.addLink(link, linkPosition); - }, - - removeLinkUi = function (link) { - graphics.releaseLink(link); - }, - - listenNodeEvents = function (node) { - var wasPinned = false; - var nodeInteractive = (typeof interactive === 'string' && interactive.indexOf('node') !== -1) || interactive; - if (!nodeInteractive) { - return; - } - - // TODO: This may not be memory efficient. Consider reusing handlers object. - inputManager.bindDragNDrop(node, { - onStart : function () { - wasPinned = layout.isNodePinned(node); - layout.pinNode(node, true); - userInteraction = true; - resetStable(); - }, - onDrag : function (e, offset) { - var oldPos = layout.getNodePosition(node.id); - layout.setNodePosition(node, - oldPos.x + offset.x / transform.scale, - oldPos.y + offset.y / transform.scale); - - userInteraction = true; - - renderGraph(); - }, - onStop : function () { - layout.pinNode(node, wasPinned); - userInteraction = false; - } - }); - }, - - releaseNodeEvents = function (node) { - inputManager.bindDragNDrop(node, null); - }, - - initDom = function () { - graphics.init(container); - - graph.forEachNode(createNodeUi); - - if (settings.renderLinks) { - graph.forEachLink(createLinkUi); - } - }, - - releaseDom = function () { - graphics.release(container); - }, - - processNodeChange = function (change) { - var node = change.node; - - if (change.changeType === 'add') { - createNodeUi(node); - listenNodeEvents(node); - if (updateCenterRequired) { - updateCenter(); - } - } else if (change.changeType === 'remove') { - releaseNodeEvents(node); - removeNodeUi(node); - if (graph.getNodesCount() === 0) { - updateCenterRequired = true; // Next time when node is added - center the graph. - } - } else if (change.changeType === 'update') { - releaseNodeEvents(node); - removeNodeUi(node); - - createNodeUi(node); - listenNodeEvents(node); - } - }, - - processLinkChange = function (change) { - var link = change.link; - if (change.changeType === 'add') { - if (settings.renderLinks) { createLinkUi(link); } - } else if (change.changeType === 'remove') { - if (settings.renderLinks) { removeLinkUi(link); } - } else if (change.changeType === 'update') { - throw 'Update type is not implemented. TODO: Implement me!'; - } - }, - - onGraphChanged = function (changes) { - var i, change; - for (i = 0; i < changes.length; i += 1) { - change = changes[i]; - if (change.node) { - processNodeChange(change); - } else if (change.link) { - processLinkChange(change); - } - } - - resetStable(); - }, - - onWindowResized = function () { - updateCenter(); - onRenderFrame(); - }, - - releaseContainerDragManager = function () { - if (containerDrag) { - containerDrag.release(); - containerDrag = null; - } - }, - - releaseGraphEvents = function () { - if (graphEvents) { - // Interesting.. why is it not null? Anyway: - graphEvents.stop('changed', onGraphChanged); - graphEvents = null; - } - }, - - scale = function (out, scrollPoint) { - if (!scrollPoint) { - var containerSize = Viva.Graph.Utils.getDimension(container); - scrollPoint = { - x: containerSize.width/2, - y: containerSize.height/2 - }; - } - var scaleFactor = Math.pow(1 + 0.4, out ? -0.2 : 0.2); - transform.scale = graphics.scale(scaleFactor, scrollPoint); - - renderGraph(); - publicEvents.fire('scale', transform.scale); - - return transform.scale; - }, - - listenToEvents = function () { - windowEvents.on('resize', onWindowResized); - - releaseContainerDragManager(); - var canDrag = (typeof interactive === 'string' && interactive.indexOf('drag') !== -1) || interactive; - if (canDrag) { - containerDrag = Viva.Graph.Utils.dragndrop(container); - containerDrag.onDrag(function (e, offset) { - viewPortOffset.x += offset.x; - viewPortOffset.y += offset.y; - graphics.translateRel(offset.x, offset.y); - - renderGraph(); - }); - } - - var canScroll = (typeof interactive === 'string' && interactive.indexOf('scroll') !== -1) || interactive; - if (canScroll) { - containerDrag.onScroll(function (e, scaleOffset, scrollPoint) { - scale(scaleOffset < 0, scrollPoint); - }); - } - - graph.forEachNode(listenNodeEvents); - - releaseGraphEvents(); - graphEvents = Viva.Graph.Utils.events(graph); - graphEvents.on('changed', onGraphChanged); - }, - - stopListenToEvents = function () { - rendererInitialized = false; - releaseGraphEvents(); - releaseContainerDragManager(); - windowEvents.stop('resize', onWindowResized); - publicEvents.removeAllListeners(); - animationTimer.stop(); - - graph.forEachLink(function (link) { - if (settings.renderLinks) { removeLinkUi(link); } - }); - - graph.forEachNode(function (node) { - releaseNodeEvents(node); - removeNodeUi(node); - }); - - layout.dispose(); - releaseDom(); - }; - - return { - /** - * Performs rendering of the graph. - * - * @param iterationsCount if specified renderer will run only given number of iterations - * and then stop. Otherwise graph rendering is performed infinitely. - * - * Note: if rendering stopped by used started dragging nodes or new nodes were added to the - * graph renderer will give run more iterations to reflect changes. - */ - run : function (iterationsCount) { - - if (!rendererInitialized) { - prepareSettings(); - prerender(); - - updateCenter(); - initDom(); - listenToEvents(); - - rendererInitialized = true; - } - - renderIterations(iterationsCount); - - return this; - }, - - reset : function () { - graphics.resetScale(); - updateCenter(); - transform.scale = 1; - }, - - pause : function () { - isPaused = true; - animationTimer.stop(); - }, - - resume : function () { - isPaused = false; - animationTimer.restart(); - }, - - rerender : function () { - renderGraph(); - return this; - }, - - zoomOut: function () { - return scale(true); - }, - - zoomIn: function () { - return scale(false); - }, - - /** - * Centers renderer at x,y graph's coordinates - */ - moveTo: function (x, y) { - graphics.graphCenterChanged(transform.offsetX - x * transform.scale, transform.offsetY - y * transform.scale); - renderGraph(); - }, - - /** - * Gets current graphics object - */ - getGraphics: function () { - return graphics; - }, - - /** - * Removes this renderer and deallocates all resources/timers - */ - dispose : function () { - stopListenToEvents(); // I quit! - }, - - on : function (eventName, callback) { - publicEvents.addEventListener(eventName, callback); - return this; - }, - - off : function (eventName, callback) { - publicEvents.removeEventListener(eventName, callback); - return this; - } - }; -}; -Viva.Graph.serializer = function () { - var checkJSON = function () { - if (typeof JSON === 'undefined' || !JSON.stringify || !JSON.parse) { - throw 'JSON serializer is not defined.'; - } - }, - - nodeTransformStore = function (node) { - return { id : node.id, data: node.data }; - }, - - linkTransformStore = function (link) { - return { - fromId : link.fromId, - toId: link.toId, - data : link.data - }; - }, - - nodeTransformLoad = function (node) { - return node; - }, - - linkTransformLoad = function (link) { - return link; - }; - - return { - /** - * Saves graph to JSON format. - * - * NOTE: ECMAScript 5 (or alike) JSON object is required to be defined - * to get proper output. - * - * @param graph to be saved in JSON format. - * @param nodeTransform optional callback function(node) which returns what should be passed into nodes collection - * @param linkTransform optional callback functions(link) which returns what should be passed into the links collection - */ - storeToJSON : function (graph, nodeTransform, linkTransform) { - if (!graph) { throw 'Graph is not defined'; } - checkJSON(); - - nodeTransform = nodeTransform || nodeTransformStore; - linkTransform = linkTransform || linkTransformStore; - - var store = { - nodes : [], - links : [] - }; - - graph.forEachNode(function (node) { store.nodes.push(nodeTransform(node)); }); - graph.forEachLink(function (link) { store.links.push(linkTransform(link)); }); - - return JSON.stringify(store); - }, - - /** - * Restores graph from JSON string created by storeToJSON() method. - * - * NOTE: ECMAScript 5 (or alike) JSON object is required to be defined - * to get proper output. - * - * @param jsonString is a string produced by storeToJSON() method. - * @param nodeTransform optional callback function(node) which accepts deserialized node and returns object with - * 'id' and 'data' properties. - * @param linkTransform optional callback functions(link) which accepts deserialized link and returns link object with - * 'fromId', 'toId' and 'data' properties. - */ - loadFromJSON : function (jsonString, nodeTransform, linkTransform) { - if (typeof jsonString !== 'string') { throw 'String expected in loadFromJSON() method'; } - checkJSON(); - - nodeTransform = nodeTransform || nodeTransformLoad; - linkTransform = linkTransform || linkTransformLoad; - - var store = JSON.parse(jsonString), - graph = Viva.Graph.graph(), - i; - - if (!store || !store.nodes || !store.links) { throw 'Passed json string does not represent valid graph'; } - - for (i = 0; i < store.nodes.length; ++i) { - var parsedNode = nodeTransform(store.nodes[i]); - if (!parsedNode.hasOwnProperty('id')) { throw 'Graph node format is invalid. Node.id is missing'; } - - graph.addNode(parsedNode.id, parsedNode.data); - } - - for (i = 0; i < store.links.length; ++i) { - var link = linkTransform(store.links[i]); - if (!link.hasOwnProperty('fromId') || !link.hasOwnProperty('toId')) { throw 'Graph link format is invalid. Both fromId and toId are required'; } - - graph.addLink(link.fromId, link.toId, link.data); - } - - return graph; - } - }; -}; -/** - * @fileOverview Centrality calcuation algorithms. - * - * @see http://en.wikipedia.org/wiki/Centrality - * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com - */ - -Viva.Graph.centrality = function () { - var singleSourceShortestPath = function (graph, node, oriented) { - // I'm using the same naming convention used in http://www.inf.uni-konstanz.de/algo/publications/b-fabc-01.pdf - // sorry about cryptic names. - var P = {}, // predcessors lists. - S = [], - sigma = {}, - d = {}, - Q = [node.id], - v, - dV, - sigmaV, - processNode = function (w) { - // w found for the first time? - if (!d.hasOwnProperty(w.id)) { - Q.push(w.id); - d[w.id] = dV + 1; - } - // Shortest path to w via v? - if (d[w.id] === dV + 1) { - sigma[w.id] += sigmaV; - P[w.id].push(v); - } - }; - - graph.forEachNode(function (t) { - P[t.id] = []; - sigma[t.id] = 0; - }); - - d[node.id] = 0; - sigma[node.id] = 1; - - while (Q.length) { // Using BFS to find shortest paths - v = Q.shift(); - dV = d[v]; - sigmaV = sigma[v]; - - S.push(v); - graph.forEachLinkedNode(v, processNode, oriented); - } - - return { - S : S, - P : P, - sigma : sigma - }; - }, - - accumulate = function (betweenness, shortestPath, s) { - var delta = {}, - S = shortestPath.S, - i, - w, - coeff, - pW, - v; - - for (i = 0; i < S.length; i += 1) { - delta[S[i]] = 0; - } - - // S returns vertices in order of non-increasing distance from s - while (S.length) { - w = S.pop(); - coeff = (1 + delta[w]) / shortestPath.sigma[w]; - pW = shortestPath.P[w]; - - for (i = 0; i < pW.length; i += 1) { - v = pW[i]; - delta[v] += shortestPath.sigma[v] * coeff; - } - - if (w !== s) { - betweenness[w] += delta[w]; - } - } - }, - - sortBetweennes = function (b) { - var sorted = [], - key; - for (key in b) { - if (b.hasOwnProperty(key)) { - sorted.push({ key : key, value : b[key]}); - } - } - - return sorted.sort(function (x, y) { return y.value - x.value; }); - }; - - return { - - /** - * Compute the shortest-path betweenness centrality for all nodes in a graph. - * - * Betweenness centrality of a node `n` is the sum of the fraction of all-pairs - * shortest paths that pass through `n`. Runtime O(n * v) for non-weighted graphs. - * - * @see http://en.wikipedia.org/wiki/Centrality#Betweenness_centrality - * - * @see A Faster Algorithm for Betweenness Centrality. - * Ulrik Brandes, Journal of Mathematical Sociology 25(2):163-177, 2001. - * http://www.inf.uni-konstanz.de/algo/publications/b-fabc-01.pdf - * - * @see Ulrik Brandes: On Variants of Shortest-Path Betweenness - * Centrality and their Generic Computation. - * Social Networks 30(2):136-145, 2008. - * http://www.inf.uni-konstanz.de/algo/publications/b-vspbc-08.pdf - * - * @see Ulrik Brandes and Christian Pich: Centrality Estimation in Large Networks. - * International Journal of Bifurcation and Chaos 17(7):2303-2318, 2007. - * http://www.inf.uni-konstanz.de/algo/publications/bp-celn-06.pdf - * - * @param graph for which we are calculating betweenness centrality. Non-weighted graphs are only supported - */ - betweennessCentrality : function (graph) { - var betweennes = {}, - shortestPath; - graph.forEachNode(function (node) { - betweennes[node.id] = 0; - }); - - graph.forEachNode(function (node) { - shortestPath = singleSourceShortestPath(graph, node); - accumulate(betweennes, shortestPath, node); - }); - - return sortBetweennes(betweennes); - }, - - /** - * Calculates graph nodes degree centrality (in/out or both). - * - * @see http://en.wikipedia.org/wiki/Centrality#Degree_centrality - * - * @param graph for which we are calculating centrality. - * @param kind optional parameter. Valid values are - * 'in' - calculate in-degree centrality - * 'out' - calculate out-degree centrality - * - if it's not set generic degree centrality is calculated - */ - degreeCentrality : function (graph, kind) { - var calcDegFunction, - sortedDegrees = [], - result = [], - degree; - - kind = (kind || 'both').toLowerCase(); - if (kind === 'in') { - calcDegFunction = function (links, nodeId) { - var total = 0, - i; - for (i = 0; i < links.length; i += 1) { - total += (links[i].toId === nodeId) ? 1 : 0; - } - return total; - }; - } else if (kind === 'out') { - calcDegFunction = function (links, nodeId) { - var total = 0, - i; - for (i = 0; i < links.length; i += 1) { - total += (links[i].fromId === nodeId) ? 1 : 0; - } - return total; - }; - } else if (kind === 'both') { - calcDegFunction = function (links) { - return links.length; - }; - } else { - throw 'Expected centrality degree kind is: in, out or both'; - } - - graph.forEachNode(function (node) { - var links = graph.getLinks(node.id), - nodeDeg = calcDegFunction(links, node.id); - - if (!sortedDegrees.hasOwnProperty(nodeDeg)) { - sortedDegrees[nodeDeg] = [node.id]; - } else { - sortedDegrees[nodeDeg].push(node.id); - } - }); - - for (degree in sortedDegrees) { - if (sortedDegrees.hasOwnProperty(degree)) { - var nodes = sortedDegrees[degree], - j; - if (nodes) { - for (j = 0; j < nodes.length; ++j) { - result.unshift({key : nodes[j], value : parseInt(degree, 10)}); - } - } - } - } - - return result; - } - }; -};/** - * @fileOverview Community structure detection algorithms - * - * @see http://en.wikipedia.org/wiki/Community_structure - * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com - */ - -Viva.Graph.community = function () { - return { - /** - * Implementation of Speaker-listener Label Propagation Algorithm (SLPA) of - * Jierui Xie and Boleslaw K. Szymanski. - * - * @see http://arxiv.org/pdf/1109.5720v3.pdf - * @see https://sites.google.com/site/communitydetectionslpa/ - */ - slpa : function (graph, T, r) { - var algorithm = Viva.Graph._community.slpaAlgorithm(graph, T, r); - return algorithm.run(); - } - }; -};Viva.Graph._community = {}; - -/** - * Implementation of Speaker-listener Label Propagation Algorithm (SLPA) of - * Jierui Xie and Boleslaw K. Szymanski. - * - * @see http://arxiv.org/pdf/1109.5720v3.pdf - * @see https://sites.google.com/site/communitydetectionslpa/ - */ -Viva.Graph._community.slpaAlgorithm = function (graph, T, r) { - T = T || 100; // number of evaluation iterations. Should be at least 20. Influence memory consumption by O(n * T); - r = r || 0.3; // community threshold on scale from 0 to 1. Value greater than 0.5 result in disjoint communities. - - var random = Viva.random(1331782216905), - shuffleRandom = Viva.random('Greeting goes to you, ', 'dear reader'), - - calculateCommunities = function (nodeMemory, threshold) { - var communities = []; - nodeMemory.forEachUniqueWord(function (word, count) { - if (count > threshold) { - communities.push({name : word, probability : count / T }); - } else { - return true; // stop enumeration, nothing more popular after this word. - } - }); - - return communities; - }, - - init = function (graph) { - var algoNodes = []; - graph.forEachNode(function (node) { - var memory = Viva.Graph._community.occuranceMap(random); - memory.add(node.id); - - node.slpa = { memory : memory }; - algoNodes.push(node.id); - }); - - return algoNodes; - }, - - evaluate = function (graph, nodes) { - var shuffle = Viva.randomIterator(nodes, shuffleRandom), - t, - - /** - * One iteration of SLPA. - */ - processNode = function (nodeId) { - var listner = graph.getNode(nodeId), - saidWords = Viva.Graph._community.occuranceMap(random); - - graph.forEachLinkedNode(nodeId, function (speakerNode) { - var word = speakerNode.slpa.memory.getRandomWord(); - saidWords.add(word); - }); - - // selecting the most popular label from what it observed in the current step - var heard = saidWords.getMostPopularFair(); - listner.slpa.memory.add(heard); - }; - - for (t = 0; t < T - 1; ++t) { // -1 is because one 'step' was during init phase - shuffle.forEach(processNode); - } - }, - - postProcess = function (graph) { - var communities = {}; - - graph.forEachNode(function (node) { - var nodeCommunities = calculateCommunities(node.slpa.memory, r * T), - i; - - for (i = 0; i < nodeCommunities.length; ++i) { - var communityName = nodeCommunities[i].name; - if (communities.hasOwnProperty(communityName)) { - communities[communityName].push(node.id); - } else { - communities[communityName] = [node.id]; - } - } - - node.communities = nodeCommunities; // TODO: I doesn't look right to augment node's properties. No? - - // Speaking of memory. Node memory created by slpa is really expensive. Release it: - node.slpa = null; - delete node.slpa; - }); - - return communities; - }; - - return { - - /** - * Executes SLPA algorithm. The function returns dictionary of discovered communities: - * { - * 'communityName1' : [nodeId1, nodeId2, .., nodeIdN], - * 'communityName2' : [nodeIdK1, nodeIdK2, .., nodeIdKN], - * ... - * }; - * - * After algorithm is done each node is also augmented with new property 'communities': - * - * node.communities = [ - * {name: 'communityName1', probability: 0.78}, - * {name: 'communityName2', probability: 0.63}, - * ... - * ]; - * - * 'probability' is always higher than 'r' parameter and denotes level of confidence - * with which we think node belongs to community. - * - * Runtime is O(T * m), where m is total number of edges, and T - number of algorithm iterations. - * - */ - run : function () { - var nodes = init(graph); - - evaluate(graph, nodes); - - return postProcess(graph); - } - }; -}; - -/** - * A data structure which serves as node memory during SLPA execution. The main idea is to - * simplify operations on memory such as - * - add word to memory, - * - get random word from memory, with probablity proportional to word occurrence in the memory - * - get the most popular word in memory - * - * TODO: currently this structure is extremely inefficient in terms of memory. I think it could be - * optimized. - */ -Viva.Graph._community.occuranceMap = function (random) { - random = random || Viva.random(); - - var wordsCount = {}, - allWords = [], - dirtyPopularity = false, - uniqueWords = [], - - rebuildPopularityArray = function () { - var key; - - uniqueWords.length = 0; - for (key in wordsCount) { - if (wordsCount.hasOwnProperty(key)) { - uniqueWords.push(key); - } - } - - uniqueWords.sort(function (x, y) { - var result = wordsCount[y] - wordsCount[x]; - if (result) { - return result; - } - - // Not only number of occurances matters but order of keys also does. - // for ... in implementation in different browsers results in different - // order, and if we want to have same categories accross all browsers - // we should order words by key names too: - if (x < y) { return -1; } - if (x > y) { return 1; } - - return 0; - }); - }, - - ensureUniqueWordsUpdated = function () { - if (dirtyPopularity) { - rebuildPopularityArray(); - dirtyPopularity = false; - } - }; - - return { - - /** - * Adds a new word to the collection of words. - */ - add : function (word) { - word = String(word); - if (wordsCount.hasOwnProperty(word)) { - wordsCount[word] += 1; - } else { - wordsCount[word] = 1; - } - - allWords.push(word); - dirtyPopularity = true; - }, - - /** - * Gets number of occurances for a given word. If word is not present in the dictionary - * zero is returned. - */ - getWordCount : function (word) { - return wordsCount[word] || 0; - }, - - /** - * Gets the most popular word in the map. If multiple words are at the same position - * random word among them is choosen. - * - */ - getMostPopularFair : function () { - if (allWords.length === 1) { - return allWords[0]; // optimizes speed for simple case. - } - - ensureUniqueWordsUpdated(); - - var maxCount = 0, - i; - - for (i = 1; i < uniqueWords.length; ++i) { - if (wordsCount[uniqueWords[i - 1]] !== wordsCount[uniqueWords[i]]) { - break; // other words are less popular... not interested. - } else { - maxCount += 1; - } - } - - maxCount += 1; // to include upper bound. i.e. random words between [0, maxCount] (not [0, maxCount) ). - return uniqueWords[random.next(maxCount)]; - }, - - /** - * Selects a random word from map with probability proportional - * to the occurrence frequency of words. - */ - getRandomWord : function () { - if (allWords.length === 0) { - throw 'The occurance map is empty. Cannot get empty word'; - } - - return allWords[random.next(allWords.length)]; - }, - - /** - * Enumerates all unique words in the map, and calls - * callback(word, occuranceCount) function on each word. Callback - * can return true value to stop enumeration. - * - * Note: enumeration is guaranteed in to run in decreasing order. - */ - forEachUniqueWord : function (callback) { - if (typeof callback !== 'function') { - throw 'Function callback is expected to enumerate all words'; - } - var i; - - ensureUniqueWordsUpdated(); - - for (i = 0; i < uniqueWords.length; ++i) { - var word = uniqueWords[i], - count = wordsCount[word]; - - var stop = callback(word, count); - if (stop) { - break; - } - } - } - }; -};/** - * @fileOverview Contains collection of graph generators. - * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com - */ - -Viva.Graph.generator = function () { - - return { - /** - * Generates complete graph Kn. - * - * @param n represents number of nodes in the complete graph. - */ - complete : function (n) { - if (!n || n < 1) { - throw { message: "At least two nodes expected for complete graph" }; - } - - var g = Viva.Graph.graph(), - i, - j; - - g.Name = "Complete K" + n; - - for (i = 0; i < n; ++i) { - for (j = i + 1; j < n; ++j) { - if (i !== j) { - g.addLink(i, j); - } - } - } - - return g; - }, - - /** - * Generates complete bipartite graph K n,m. Each node in the - * first partition is connected to all nodes in the second partition. - * - * @param n represents number of nodes in the first graph partition - * @param m represents number of nodes in the second graph partition - */ - completeBipartite : function (n, m) { - if (!n || !m || n < 0 || m < 0) { - throw { message: "Graph dimensions are invalid. Number of nodes in each partition should be greate than 0" }; - } - - var g = Viva.Graph.graph(), - i, - j; - - g.Name = "Complete K " + n + "," + m; - for (i = 0; i < n; ++i) { - for (j = n; j < n + m; ++j) { - g.addLink(i, j); - } - } - - return g; - }, - /** - * Generates a graph in a form of a ladder with n steps. - * - * @param n number of steps in the ladder. - */ - ladder : function (n) { - if (!n || n < 0) { - throw { message: "Invalid number of nodes" }; - } - - var g = Viva.Graph.graph(), - i; - g.Name = "Ladder graph " + n; - - for (i = 0; i < n - 1; ++i) { - g.addLink(i, i + 1); - // first row - g.addLink(n + i, n + i + 1); - // second row - g.addLink(i, n + i); - // ladder"s step - } - - g.addLink(n - 1, 2 * n - 1); - // last step in the ladder; - - return g; - }, - - /** - * Generates a graph in a form of a circular ladder with n steps. - * - * @param n number of steps in the ladder. - */ - circularLadder : function (n) { - if (!n || n < 0) { - throw { message: "Invalid number of nodes" }; - } - - var g = this.ladder(n); - g.Name = "Circular ladder graph " + n; - - g.addLink(0, n - 1); - g.addLink(n, 2 * n - 1); - return g; - }, - /** - * Generates a graph in a form of a grid with n rows and m columns. - * - * @param n number of rows in the graph. - * @param m number of columns in the graph. - */ - grid: function (n, m) { - var g = Viva.Graph.graph(), - i, - j; - g.Name = "Grid graph " + n + "x" + m; - for (i = 0; i < n; ++i) { - for (j = 0; j < m; ++j) { - var node = i + j * n; - if (i > 0) { g.addLink(node, i - 1 + j * n); } - if (j > 0) { g.addLink(node, i + (j - 1) * n); } - } - } - - return g; - }, - - path: function (n) { - if (!n || n < 0) { - throw { message: "Invalid number of nodes" }; - } - - var g = Viva.Graph.graph(), - i; - g.Name = "Path graph " + n; - g.addNode(0); - - for (i = 1; i < n; ++i) { - g.addLink(i - 1, i); - } - - return g; - }, - - lollipop: function (m, n) { - if (!n || n < 0 || !m || m < 0) { - throw { message: "Invalid number of nodes" }; - } - - var g = this.complete(m), - i; - g.Name = "Lollipop graph. Head x Path " + m + "x" + n; - - for (i = 0; i < n; ++i) { - g.addLink(m + i - 1, m + i); - } - - return g; - }, - - /** - * Creates balanced binary tree with n levels. - */ - balancedBinTree: function (n) { - var g = Viva.Graph.graph(), - count = Math.pow(2, n), - level; - g.Name = "Balanced bin tree graph " + n; - - for (level = 1; level < count; ++level) { - var root = level, - left = root * 2, - right = root * 2 + 1; - - g.addLink(root, left); - g.addLink(root, right); - } - - return g; - }, - /** - * Generates a graph with n nodes and 0 links. - * - * @param n number of nodes in the graph. - */ - randomNoLinks : function (n) { - if (!n || n < 0) { - throw { message: "Invalid number of nodes" }; - } - - var g = Viva.Graph.graph(), - i; - g.Name = "Random graph, no Links: " + n; - for (i = 0; i < n; ++i) { - g.addNode(i); - } - - return g; - } - }; -}; -/** - * @fileOverview Defines a graph renderer that uses CSS based drawings. - * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com - */ -// The file tries to conform generic interface: -/*jshint unused: false */ - -Viva.Graph.View = Viva.Graph.View || {}; - -/** - * Performs css-based graph rendering. This module does not perform - * layout, but only visualizes nodes and edeges of the graph. - * - * NOTE: Most likely I will remove this graphics engine due to superior svg support. - * In certain cases it doesn't work and require further imporvments: - * * does not properly work for dragging. - * * does not support scaling. - * * does not support IE versions prior to IE9. - * - */ -Viva.Graph.View.cssGraphics = function () { - var container, // Where graph will be rendered - OLD_IE = "OLD_IE", - offsetX, - offsetY, - scaleX = 1, - scaleY = 1, - - transformName = (function () { - var browserName = Viva.BrowserInfo.browser, - prefix, - version; - - switch (browserName) { - case "mozilla": - prefix = "Moz"; - break; - case "webkit": - prefix = "webkit"; - break; - case "opera": - prefix = "O"; - break; - case "msie": - version = Viva.BrowserInfo.version.split(".")[0]; - if (version > 8) { - prefix = "ms"; - } else { - return OLD_IE; - } - break; - } - - if (prefix) { // CSS3 - return prefix + "Transform"; - } - // Unknown browser - return null; - }()), - - /** - * Returns a function (ui, x, y, angleRad). - * - * The function attempts to rotate "ui" dom element on "angleRad" radians - * and position it to "x" "y" coordinates. - * - * Operation works in most modern browsers that support transform css style - * and IE. - * */ - positionLink = (function () { - if (transformName === OLD_IE) { // This is old IE, use filters - return function (ui, x, y, angleRad) { - var cos = Math.cos(angleRad), - sin = Math.sin(angleRad); - - // IE 6, 7 and 8 are screwed up when it comes to transforms; - // I could not find justification for their choice of "floating" - // matrix transform origin. The following ugly code was written - // out of complete dispair. - if (angleRad < 0) { - angleRad = 2 * Math.PI + angleRad; - } - - if (angleRad < Math.PI / 2) { - ui.style.left = x + "px"; - ui.style.top = y + "px"; - } else if (angleRad < Math.PI) { - ui.style.left = x - (ui.clientWidth) * Math.cos(Math.PI - angleRad); - ui.style.top = y; - } else if (angleRad < (Math.PI + Math.PI / 2)) { - ui.style.left = x - (ui.clientWidth) * Math.cos(Math.PI - angleRad); - ui.style.top = y + (ui.clientWidth) * Math.sin(Math.PI - angleRad); - } else { - ui.style.left = x; - ui.style.top = y + ui.clientWidth * Math.sin(Math.PI - angleRad); - } - ui.style.filter = "progid:DXImageTransform.Microsoft.Matrix(sizingMethod=\"auto expand\"," + "M11=" + cos + ", M12=" + (-sin) + "," + "M21=" + sin + ", M22=" + cos + ");"; - }; - } - - if (transformName) { // Modern CSS3 browser - return function (ui, x, y, angleRad) { - ui.style.left = x + "px"; - ui.style.top = y + "px"; - - ui.style[transformName] = "rotate(" + angleRad + "rad)"; - ui.style[transformName + "Origin"] = "left"; - }; - } - - return function (ui, x, y, angleRad) { - // Don't know how to rotate links in other browsers. - }; - }()), - - nodeBuilder = function (node) { - var nodeUI = window.document.createElement("div"); - nodeUI.setAttribute("class", "node"); - return nodeUI; - }, - - nodePositionCallback = function (nodeUI, pos) { - // TODO: Remove magic 5. It should be half of the width or height of the node. - nodeUI.style.left = pos.x - 5 + "px"; - nodeUI.style.top = pos.y - 5 + "px"; - }, - - linkPositionCallback = function (linkUI, fromPos, toPos) { - var dx = fromPos.x - toPos.x, - dy = fromPos.y - toPos.y, - length = Math.sqrt(dx * dx + dy * dy); - - linkUI.style.height = "1px"; - linkUI.style.width = length + "px"; - - positionLink(linkUI, toPos.x, toPos.y, Math.atan2(dy, dx)); - }, - - linkBuilder = function (link) { - var linkUI = window.document.createElement("div"); - linkUI.setAttribute("class", "link"); - - return linkUI; - }, - - updateTransform = function () { - if (container) { - if (transformName && transformName !== OLD_IE) { - var transform = "matrix(" + scaleX + ", 0, 0," + scaleY + "," + offsetX + "," + offsetY + ")"; - container.style[transformName] = transform; - } else { - throw "Not implemented. TODO: Implement OLD_IE Filter based transform"; - } - } - }; - - return { - /** - * Sets the collback that creates node representation or creates a new node - * presentation if builderCallbackOrNode is not a function. - * - * @param builderCallbackOrNode a callback function that accepts graph node - * as a parameter and must return an element representing this node. OR - * if it's not a function it's treated as a node to which DOM element should be created. - * - * @returns If builderCallbackOrNode is a valid callback function, instance of this is returned; - * Otherwise a node representation is returned for the passed parameter. - */ - node : function (builderCallbackOrNode) { - if (builderCallbackOrNode && typeof builderCallbackOrNode !== "function") { - return nodeBuilder(builderCallbackOrNode); - } - - nodeBuilder = builderCallbackOrNode; - - return this; - }, - - /** - * Sets the collback that creates link representation or creates a new link - * presentation if builderCallbackOrLink is not a function. - * - * @param builderCallbackOrLink a callback function that accepts graph link - * as a parameter and must return an element representing this link. OR - * if it's not a function it's treated as a link to which DOM element should be created. - * - * @returns If builderCallbackOrLink is a valid callback function, instance of this is returned; - * Otherwise a link representation is returned for the passed parameter. - */ - link : function (builderCallbackOrLink) { - if (builderCallbackOrLink && typeof builderCallbackOrLink !== "function") { - return linkBuilder(builderCallbackOrLink); - } - - linkBuilder = builderCallbackOrLink; - return this; - }, - - /** - * Default input manager listens to DOM events to process nodes drag-n-drop - */ - inputManager : Viva.Input.domInputManager, - - /** - * Sets translate operation that should be applied to all nodes and links. - */ - graphCenterChanged : function (x, y) { - offsetX = x; - offsetY = y; - updateTransform(); - }, - - translateRel : function (dx, dy) { - offsetX += dx; - offsetY += dy; - updateTransform(); - }, - - scale : function (x, y) { - // TODO: implement me - return 1; - }, - - resetScale : function () { - // TODO: implement me - return this; - }, - - /** - * Called every before renderer starts rendering. - */ - beginRender : function () {}, - - /** - * Called every time when renderer finishes one step of rendering. - */ - endRender : function () {}, - /** - * Allows to override default position setter for the node with a new - * function. newPlaceCallback(node, position) is function which - * is used by updateNode(). - */ - placeNode : function (newPlaceCallback) { - nodePositionCallback = newPlaceCallback; - return this; - }, - - placeLink : function (newPlaceLinkCallback) { - linkPositionCallback = newPlaceLinkCallback; - return this; - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * providers prepare to render. - */ - init : function (parentContainer) { - container = parentContainer; - updateTransform(); - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render given link of the graph - * - * @param linkUI visual representation of the link created by link() execution. - */ - initLink : function (linkUI) { - if (container.childElementCount > 0) { - container.insertBefore(linkUI, container.firstChild); - } else { - container.appendChild(linkUI); - } - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider remove link from rendering surface. - * - * @param linkUI visual representation of the link created by link() execution. - **/ - releaseLink : function (linkUI) { - container.removeChild(linkUI); - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render given node of the graph. - * - * @param nodeUI visual representation of the node created by node() execution. - **/ - initNode : function (nodeUI) { - container.appendChild(nodeUI); - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider remove node from rendering surface. - * - * @param nodeUI visual representation of the node created by node() execution. - **/ - releaseNode : function (nodeUI) { - container.removeChild(nodeUI); - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider place given node to recommended position pos {x, y}; - */ - updateNodePosition : function (node, pos) { - nodePositionCallback(node, pos); - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider place given link of the graph - */ - updateLinkPosition : function (link, fromPos, toPos) { - linkPositionCallback(link, fromPos, toPos); - } - }; -}; -/** - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com - */ - -/** - * Simple wrapper over svg object model API, to shorten the usage syntax. - */ -Viva.Graph.svg = function (element) { - var svgns = "http://www.w3.org/2000/svg", - xlinkns = "http://www.w3.org/1999/xlink", - svgElement = element; - - if (typeof element === "string") { - svgElement = window.document.createElementNS(svgns, element); - } - - if (svgElement.vivagraphAugmented) { - return svgElement; - } - - svgElement.vivagraphAugmented = true; - - // Augment svg element (TODO: it's not safe - what if some function already exists on the prototype?): - - /** - * Gets an svg attribute from an element if value is not specified. - * OR sets a new value to the given attribute. - * - * @param name - svg attribute name; - * @param value - value to be set; - * - * @returns svg element if both name and value are specified; or value of the given attribute - * if value parameter is missing. - */ - svgElement.attr = function (name, value) { - if (arguments.length === 2) { - if (value !== null) { - svgElement.setAttributeNS(null, name, value); - } else { - svgElement.removeAttributeNS(null, name); - } - - return svgElement; - } - - return svgElement.getAttributeNS(null, name); - }; - - svgElement.append = function (element) { - var child = Viva.Graph.svg(element); - svgElement.appendChild(child); - return child; - }; - - svgElement.text = function (textContent) { - if (typeof textContent !== "undefined") { - svgElement.textContent = textContent; - return svgElement; - } - return svgElement.textContent; - }; - - svgElement.link = function (target) { - if (arguments.length) { - svgElement.setAttributeNS(xlinkns, "xlink:href", target); - return svgElement; - } - - return svgElement.getAttributeNS(xlinkns, "xlink:href"); - }; - - svgElement.children = function (selector) { - var wrappedChildren = [], - childrenCount = svgElement.childNodes.length, - i, - j; - - if (selector === undefined && svgElement.hasChildNodes()) { - for (i = 0; i < childrenCount; i++) { - wrappedChildren.push(Viva.Graph.svg(svgElement.childNodes[i])); - } - } else if (typeof selector === "string") { - var classSelector = (selector[0] === "."), - idSelector = (selector[0] === "#"), - tagSelector = !classSelector && !idSelector; - - for (i = 0; i < childrenCount; i++) { - var el = svgElement.childNodes[i]; - - // pass comments, text nodes etc. - if (el.nodeType === 1) { - var classes = el.attr("class"), - id = el.attr("id"), - tagName = el.nodeName; - - if (classSelector && classes) { - classes = classes.replace(/\s+/g, " ").split(" "); - for (j = 0; j < classes.length; j++) { - if (classSelector && classes[j] === selector.substr(1)) { - wrappedChildren.push(Viva.Graph.svg(el)); - break; - } - } - } else if (idSelector && id === selector.substr(1)) { - wrappedChildren.push(Viva.Graph.svg(el)); - break; - } else if (tagSelector && tagName === selector) { - wrappedChildren.push(Viva.Graph.svg(el)); - } - - wrappedChildren = wrappedChildren.concat(Viva.Graph.svg(el).children(selector)); - } - } - - if (idSelector && wrappedChildren.length === 1) { - return wrappedChildren[0]; - } - } - - return wrappedChildren; - }; - - return svgElement; -}; -/** - * @fileOverview Defines a graph renderer that uses SVG based drawings. - * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com - */ - -Viva.Graph.View = Viva.Graph.View || {}; - -/** - * Performs svg-based graph rendering. This module does not perform - * layout, but only visualizes nodes and edeges of the graph. - */ -Viva.Graph.View.svgGraphics = function () { - var svgContainer, - svgRoot, - offsetX, - offsetY, - initCallback, - actualScale = 1, - allNodes = {}, - allLinks = {}, -/*jshint unused: false */ - nodeBuilder = function (node) { - return Viva.Graph.svg("rect") - .attr("width", 10) - .attr("height", 10) - .attr("fill", "#00a2e8"); - }, - - nodePositionCallback = function (nodeUI, pos) { - // TODO: Remove magic 5. It should be halfo of the width or height of the node. - nodeUI.attr("x", pos.x - 5) - .attr("y", pos.y - 5); - }, - - linkBuilder = function (link) { - return Viva.Graph.svg("line") - .attr("stroke", "#999"); - }, - - linkPositionCallback = function (linkUI, fromPos, toPos) { - linkUI.attr("x1", fromPos.x) - .attr("y1", fromPos.y) - .attr("x2", toPos.x) - .attr("y2", toPos.y); - }, - - fireRescaled = function (graphics) { - // TODO: maybe we shall copy changes? - graphics.fire("rescaled"); - }, - - cachedPos = {x : 0, y: 0}, - cachedFromPos = {x : 0, y: 0}, - cachedToPos = {x : 0, y: 0}, - - updateTransform = function () { - if (svgContainer) { - var transform = "matrix(" + actualScale + ", 0, 0," + actualScale + "," + offsetX + "," + offsetY + ")"; - svgContainer.attr("transform", transform); - } - }; - - var graphics = { - getNodeUI: function (nodeId) { - return allNodes[nodeId]; - }, - - getLinkUI: function (linkId) { - return allLinks[linkId]; - }, - - /** - * Sets the callback that creates node representation. - * - * @param builderCallback a callback function that accepts graph node - * as a parameter and must return an element representing this node. - * - * @returns If builderCallbackOrNode is a valid callback function, instance of this is returned; - * Otherwise undefined value is returned - */ - node : function (builderCallback) { - if (typeof builderCallback !== "function") { - return; // todo: throw? this is not compatible with old versions - } - - nodeBuilder = builderCallback; - - return this; - }, - - /** - * Sets the callback that creates link representation - * - * @param builderCallback a callback function that accepts graph link - * as a parameter and must return an element representing this link. - * - * @returns If builderCallback is a valid callback function, instance of this is returned; - * Otherwise undefined value is returend. - */ - link : function (builderCallback) { - if (typeof builderCallback !== "function") { - return; // todo: throw? this is not compatible with old versions - } - - linkBuilder = builderCallback; - return this; - }, - - /** - * Allows to override default position setter for the node with a new - * function. newPlaceCallback(nodeUI, position, node) is function which - * is used by updateNodePosition(). - */ - placeNode : function (newPlaceCallback) { - nodePositionCallback = newPlaceCallback; - return this; - }, - - placeLink : function (newPlaceLinkCallback) { - linkPositionCallback = newPlaceLinkCallback; - return this; - }, - - /** - * Called every before renderer starts rendering. - */ - beginRender : function () {}, - - /** - * Called every time when renderer finishes one step of rendering. - */ - endRender : function () {}, - - /** - * Sets translate operation that should be applied to all nodes and links. - */ - graphCenterChanged : function (x, y) { - offsetX = x; - offsetY = y; - updateTransform(); - }, - - /** - * Default input manager listens to DOM events to process nodes drag-n-drop - */ - inputManager : Viva.Input.domInputManager, - - translateRel : function (dx, dy) { - var p = svgRoot.createSVGPoint(), - t = svgContainer.getCTM(), - origin = svgRoot.createSVGPoint().matrixTransform(t.inverse()); - - p.x = dx; - p.y = dy; - - p = p.matrixTransform(t.inverse()); - p.x = (p.x - origin.x) * t.a; - p.y = (p.y - origin.y) * t.d; - - t.e += p.x; - t.f += p.y; - - var transform = "matrix(" + t.a + ", 0, 0," + t.d + "," + t.e + "," + t.f + ")"; - svgContainer.attr("transform", transform); - }, - - scale : function (scaleFactor, scrollPoint) { - var p = svgRoot.createSVGPoint(); - p.x = scrollPoint.x; - p.y = scrollPoint.y; - - p = p.matrixTransform(svgContainer.getCTM().inverse()); // translate to svg coordinates - - // Compute new scale matrix in current mouse position - var k = svgRoot.createSVGMatrix().translate(p.x, p.y).scale(scaleFactor).translate(-p.x, -p.y), - t = svgContainer.getCTM().multiply(k); - - actualScale = t.a; - offsetX = t.e; - offsetY = t.f; - var transform = "matrix(" + t.a + ", 0, 0," + t.d + "," + t.e + "," + t.f + ")"; - svgContainer.attr("transform", transform); - - fireRescaled(this); - return actualScale; - }, + for (i = 1; i < n; ++i) { + g.addLink(i - 1, i); + } - resetScale : function () { - actualScale = 1; - var transform = "matrix(1, 0, 0, 1, 0, 0)"; - svgContainer.attr("transform", transform); - fireRescaled(this); - return this; + return g; }, - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render. - */ - init : function (container) { - svgRoot = Viva.Graph.svg("svg"); + lollipop: function (m, n) { + if (!n || n < 0 || !m || m < 0) { + throw { message: "Invalid number of nodes" }; + } - svgContainer = Viva.Graph.svg("g") - .attr("buffered-rendering", "dynamic"); + var g = this.complete(m), + i; + g.Name = "Lollipop graph. Head x Path " + m + "x" + n; - svgRoot.appendChild(svgContainer); - container.appendChild(svgRoot); - updateTransform(); - // Notify the world if someoen waited for update. TODO: should send an event - if (typeof initCallback === "function") { - initCallback(svgRoot); + for (i = 0; i < n; ++i) { + g.addLink(m + i - 1, m + i); } - }, - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider release occupied resources. - */ - release : function (container) { - if (svgRoot && container) { - container.removeChild(svgRoot); - } + return g; }, /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render given link of the graph - * - * @param link - model of a link + * Creates balanced binary tree with n levels. */ - addLink: function (link, pos) { - var linkUI = linkBuilder(link); - if (!linkUI) { return; } - linkUI.position = pos; - linkUI.link = link; - allLinks[link.id] = linkUI; - if (svgContainer.childElementCount > 0) { - svgContainer.insertBefore(linkUI, svgContainer.firstChild); - } else { - svgContainer.appendChild(linkUI); - } - return linkUI; - }, + balancedBinTree: function (n) { + var g = Viva.Graph.graph(), + count = Math.pow(2, n), + level; + g.Name = "Balanced bin tree graph " + n; - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider remove link from rendering surface. - * - * @param linkUI visual representation of the link created by link() execution. - **/ - releaseLink : function (link) { - var linkUI = allLinks[link.id]; - if (linkUI) { - svgContainer.removeChild(linkUI); - delete allLinks[link.id]; - } - }, + for (level = 1; level < count; ++level) { + var root = level, + left = root * 2, + right = root * 2 + 1; - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render given node of the graph. - * - * @param nodeUI visual representation of the node created by node() execution. - **/ - addNode : function (node, pos) { - var nodeUI = nodeBuilder(node); - if (!nodeUI) { - return; + g.addLink(root, left); + g.addLink(root, right); } - nodeUI.position = pos; - nodeUI.node = node; - allNodes[node.id] = nodeUI; - - svgContainer.appendChild(nodeUI); - - return nodeUI; - }, - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider remove node from rendering surface. - * - * @param node graph's node - **/ - releaseNode : function (node) { - var nodeUI = allNodes[node.id]; - if (nodeUI) { - svgContainer.removeChild(nodeUI); - delete allNodes[node.id]; - } + return g; }, - - renderNodes : function () { - for (var key in allNodes) { - if (allNodes.hasOwnProperty(key)) { - var nodeUI = allNodes[key]; - cachedPos.x = nodeUI.position.x; - cachedPos.y = nodeUI.position.y; - nodePositionCallback(nodeUI, cachedPos, nodeUI.node); - } + /** + * Generates a graph with n nodes and 0 links. + * + * @param n number of nodes in the graph. + */ + randomNoLinks : function (n) { + if (!n || n < 0) { + throw { message: "Invalid number of nodes" }; } - }, - renderLinks : function () { - for (var key in allLinks) { - if (allLinks.hasOwnProperty(key)) { - var linkUI = allLinks[key]; - cachedFromPos.x = linkUI.position.from.x; - cachedFromPos.y = linkUI.position.from.y; - cachedToPos.x = linkUI.position.to.x; - cachedToPos.y = linkUI.position.to.y; - linkPositionCallback(linkUI, cachedFromPos, cachedToPos, linkUI.link); - } + var g = Viva.Graph.graph(), + i; + g.Name = "Random graph, no Links: " + n; + for (i = 0; i < n; ++i) { + g.addNode(i); } - }, - /** - * Returns root element which hosts graphics. - */ - getGraphicsRoot : function (callbackWhenReady) { - // todo: should fire an event, instead of having this context. - if (typeof callbackWhenReady === "function") { - if (svgRoot) { - callbackWhenReady(svgRoot); - } else { - initCallback = callbackWhenReady; - } - } - return svgRoot; - }, - /** - * Returns root svg element. - * - * Note: This is internal method specific to this renderer - */ - getSvgRoot : function () { - return svgRoot; + return g; } }; - - // Let graphics fire events before we return it to the caller. - Viva.Graph.Utils.events(graphics).extend(); - - return graphics; }; /** - * @fileOverview I used this class to render links UI within - * node. Lesser SVG elements is proven to improve performance - * but I'm not happy with the code result here. Probably this class - * will be removed from future versions. + * @fileOverview Defines a graph renderer that uses CSS based drawings. * * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com */ +// The file tries to conform generic interface: +/*jshint unused: false */ -Viva.Graph.View.svgNodeFactory = function (graph) { - var defaultColor = "#999", - geom = Viva.Graph.geom(), - - attachCustomContent = function (nodeUI) { - nodeUI.size = {w: 10, h: 10}; - nodeUI.append("rect") - .attr("width", nodeUI.size.w) - .attr("height", nodeUI.size.h) - .attr("stroke", "orange") - .attr("fill", "orange"); - }, - - nodeSize = function (nodeUI) { - return nodeUI.size; - }; - - - return { - node : function (node) { - var nodeUI = Viva.Graph.svg("g"); - - attachCustomContent(nodeUI, node); - nodeUI.nodeId = node.id; - return nodeUI; - }, - - link : function (link) { - var fromNode = graph.getNode(link.fromId), - nodeUI = fromNode && fromNode.ui; - - if (nodeUI && !nodeUI.linksContainer) { - var nodeLinks = Viva.Graph.svg("path") - .attr("stroke", defaultColor); - nodeUI.linksContainer = nodeLinks; - return nodeLinks; - } - - return null; - }, - - /** - * Sets a callback function for custom nodes contnet. - * @param conentCreator(nodeUI, node) - callback function which returns a node content UI. - * Image, for example. - * @param sizeProvider(nodeUI) - a callback function which accepts nodeUI returned by - * contentCreator and returns it"s custom rectangular size. - * - */ - customContent : function (contentCreator, sizeProvider) { - if (typeof contentCreator !== "function" || - typeof sizeProvider !== "function") { - throw "Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)"; - } - - attachCustomContent = contentCreator; - nodeSize = sizeProvider; - }, +Viva.Graph.View = Viva.Graph.View || {}; - placeNode : function (nodeUI, fromNodePos) { - var linksPath = "", - fromNodeSize = nodeSize(nodeUI); +/** + * Performs css-based graph rendering. This module does not perform + * layout, but only visualizes nodes and edeges of the graph. + * + * NOTE: Most likely I will remove this graphics engine due to superior svg support. + * In certain cases it doesn't work and require further imporvments: + * * does not properly work for dragging. + * * does not support scaling. + * * does not support IE versions prior to IE9. + * + */ +Viva.Graph.View.cssGraphics = function () { + var container, // Where graph will be rendered + OLD_IE = "OLD_IE", + offsetX, + offsetY, + scaleX = 1, + scaleY = 1, - graph.forEachLinkedNode(nodeUI.nodeId, function (linkedNode, link) { - if (!linkedNode.position || !linkedNode.ui) { - return; // not yet defined - ignore. - } + transformName = (function () { + var browserName = Viva.BrowserInfo.browser, + prefix, + version; - if (linkedNode.ui === nodeUI) { - return; // incoming link - ignore; - } - if (link.fromId !== nodeUI.nodeId) { - return; // we process only outgoing links. + switch (browserName) { + case "mozilla": + prefix = "Moz"; + break; + case "webkit": + prefix = "webkit"; + break; + case "opera": + prefix = "O"; + break; + case "msie": + version = Viva.BrowserInfo.version.split(".")[0]; + if (version > 8) { + prefix = "ms"; + } else { + return OLD_IE; } + break; + } - var toNodeSize = nodeSize(linkedNode.ui), - toNodePos = linkedNode.position; - - var from = geom.intersectRect( - fromNodePos.x - fromNodeSize.w / 2, // left - fromNodePos.y - fromNodeSize.h / 2, // top - fromNodePos.x + fromNodeSize.w / 2, // right - fromNodePos.y + fromNodeSize.h / 2, // bottom - fromNodePos.x, - fromNodePos.y, - toNodePos.x, - toNodePos.y - ) || fromNodePos; - - var to = geom.intersectRect( - toNodePos.x - toNodeSize.w / 2, // left - toNodePos.y - toNodeSize.h / 2, // top - toNodePos.x + toNodeSize.w / 2, // right - toNodePos.y + toNodeSize.h / 2, // bottom - toNodePos.x, - toNodePos.y, - fromNodePos.x, - fromNodePos.y - ) || toNodePos; - - linksPath += "M" + Math.round(from.x) + " " + Math.round(from.y) + - "L" + Math.round(to.x) + " " + Math.round(to.y); - }); - - nodeUI.attr("transform", - "translate(" + (fromNodePos.x - fromNodeSize.w / 2) + ", " + - (fromNodePos.y - fromNodeSize.h / 2) + ")"); - if (linksPath !== "" && nodeUI.linksContainer) { - nodeUI.linksContainer.attr("d", linksPath); + if (prefix) { // CSS3 + return prefix + "Transform"; } - } + // Unknown browser + return null; + }()), - }; -}; -/** - * @fileOverview Utility functions for webgl rendering. - * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com - */ + /** + * Returns a function (ui, x, y, angleRad). + * + * The function attempts to rotate "ui" dom element on "angleRad" radians + * and position it to "x" "y" coordinates. + * + * Operation works in most modern browsers that support transform css style + * and IE. + * */ + positionLink = (function () { + if (transformName === OLD_IE) { // This is old IE, use filters + return function (ui, x, y, angleRad) { + var cos = Math.cos(angleRad), + sin = Math.sin(angleRad); -Viva.Graph.webgl = function (gl) { - var createShader = function (shaderText, type) { - var shader = gl.createShader(type); - gl.shaderSource(shader, shaderText); - gl.compileShader(shader); + // IE 6, 7 and 8 are screwed up when it comes to transforms; + // I could not find justification for their choice of "floating" + // matrix transform origin. The following ugly code was written + // out of complete dispair. + if (angleRad < 0) { + angleRad = 2 * Math.PI + angleRad; + } - if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { - var msg = gl.getShaderInfoLog(shader); - window.alert(msg); - throw msg; + if (angleRad < Math.PI / 2) { + ui.style.left = x + "px"; + ui.style.top = y + "px"; + } else if (angleRad < Math.PI) { + ui.style.left = x - (ui.clientWidth) * Math.cos(Math.PI - angleRad); + ui.style.top = y; + } else if (angleRad < (Math.PI + Math.PI / 2)) { + ui.style.left = x - (ui.clientWidth) * Math.cos(Math.PI - angleRad); + ui.style.top = y + (ui.clientWidth) * Math.sin(Math.PI - angleRad); + } else { + ui.style.left = x; + ui.style.top = y + ui.clientWidth * Math.sin(Math.PI - angleRad); + } + ui.style.filter = "progid:DXImageTransform.Microsoft.Matrix(sizingMethod=\"auto expand\"," + "M11=" + cos + ", M12=" + (-sin) + "," + "M21=" + sin + ", M22=" + cos + ");"; + }; } - return shader; - }; + if (transformName) { // Modern CSS3 browser + return function (ui, x, y, angleRad) { + ui.style.left = x + "px"; + ui.style.top = y + "px"; - return { - createProgram : function (vertexShaderSrc, fragmentShaderSrc) { - var program = gl.createProgram(), - vs = createShader(vertexShaderSrc, gl.VERTEX_SHADER), - fs = createShader(fragmentShaderSrc, gl.FRAGMENT_SHADER); + ui.style[transformName] = "rotate(" + angleRad + "rad)"; + ui.style[transformName + "Origin"] = "left"; + }; + } - gl.attachShader(program, vs); - gl.attachShader(program, fs); - gl.linkProgram(program); + return function (ui, x, y, angleRad) { + // Don't know how to rotate links in other browsers. + }; + }()), - if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { - var msg = gl.getShaderInfoLog(program); - window.alert(msg); - throw msg; - } + nodeBuilder = function (node) { + var nodeUI = window.document.createElement("div"); + nodeUI.setAttribute("class", "node"); + return nodeUI; + }, - return program; + nodePositionCallback = function (nodeUI, pos) { + // TODO: Remove magic 5. It should be half of the width or height of the node. + nodeUI.style.left = pos.x - 5 + "px"; + nodeUI.style.top = pos.y - 5 + "px"; }, - extendArray : function (buffer, itemsInBuffer, elementsPerItem) { - if ((itemsInBuffer + 1) * elementsPerItem > buffer.length) { - // Every time we run out of space create new array twice bigger. - // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs - var extendedArray = new Float32Array(buffer.length * elementsPerItem * 2); - extendedArray.set(buffer); + linkPositionCallback = function (linkUI, fromPos, toPos) { + var dx = fromPos.x - toPos.x, + dy = fromPos.y - toPos.y, + length = Math.sqrt(dx * dx + dy * dy); - return extendedArray; - } + linkUI.style.height = "1px"; + linkUI.style.width = length + "px"; - return buffer; + positionLink(linkUI, toPos.x, toPos.y, Math.atan2(dy, dx)); }, - copyArrayPart : function (array, to, from, elementsCount) { - var i; - for (i = 0; i < elementsCount; ++i) { - array[to + i] = array[from + i]; - } - }, + linkBuilder = function (link) { + var linkUI = window.document.createElement("div"); + linkUI.setAttribute("class", "link"); - swapArrayPart : function (array, from, to, elementsCount) { - var i; - for (i = 0; i < elementsCount; ++i) { - var tmp = array[from + i]; - array[from + i] = array[to + i]; - array[to + i] = tmp; - } + return linkUI; }, - getLocations : function (program, uniformOrAttributeNames) { - var foundLocations = {}, - i; - for (i = 0; i < uniformOrAttributeNames.length; ++i) { - var name = uniformOrAttributeNames[i], - location = -1; - if (name.indexOf("a_") === 0) { - location = gl.getAttribLocation(program, name); - if (location === -1) { - throw "Program doesn't have required attribute: " + name; - } - - foundLocations[name.slice(2)] = location; - } else if (name.indexOf("u_") === 0) { - location = gl.getUniformLocation(program, name); - if (location === null) { - throw "Program doesn't have required uniform: " + name; - } - - foundLocations[name.slice(2)] = location; + updateTransform = function () { + if (container) { + if (transformName && transformName !== OLD_IE) { + var transform = "matrix(" + scaleX + ", 0, 0," + scaleY + "," + offsetX + "," + offsetY + ")"; + container.style[transformName] = transform; } else { - throw "Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'"; + throw "Not implemented. TODO: Implement OLD_IE Filter based transform"; } } + }; - return foundLocations; - }, - - context : gl - }; -}; -/** - * @fileOverview Defines a model objects to represents graph rendering - * primitives in webglGraphics. - * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com - */ - -Viva.Graph.View.WebglUtils = function () { }; - -/** - * Parses various color strings and returns color value used in webgl shaders. - */ -Viva.Graph.View.WebglUtils.prototype.parseColor = function (color) { - var parsedColor = 0x009ee8ff; - - if (typeof color === 'string' && color) { - if (color.length === 4) { // #rgb - color = color.replace(/([^#])/g, '$1$1'); // duplicate each letter except first #. - } - if (color.length === 9) { // #rrggbbaa - parsedColor = parseInt(color.substr(1), 16); - } else if (color.length === 7) { // or #rrggbb. - parsedColor = (parseInt(color.substr(1), 16) << 8) | 0xff; - } else { - throw 'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: ' + color; - } - } else if (typeof color === 'number') { - parsedColor = color; - } - - return parsedColor; -}; - -Viva.Graph.View._webglUtil = new Viva.Graph.View.WebglUtils(); // reuse this instance internally. - -/** - * Defines a webgl line. This class has no rendering logic at all, - * it's just passed to corresponding shader and the shader should - * figure out how to render it. - * - * @see Viva.Graph.View.webglLinkShader.position - */ -Viva.Graph.View.webglLine = function (color) { - return { - /** - * Gets or sets color of the line. If you set this property externally - * make sure it always come as integer of 0xRRGGBBAA format - */ - color : Viva.Graph.View._webglUtil.parseColor(color) - }; -}; - -/** - * Can be used as a callback in the webglGraphics.node() function, to - * create a custom looking node. - * - * @param size - size of the node in pixels. - * @param color - color of the node in '#rrggbbaa' or '#rgb' format. - */ -Viva.Graph.View.webglSquare = function (size, color) { - return { - /** - * Gets or sets size of the sqare side. - */ - size : typeof size === 'number' ? size : 10, - - /** - * Gets or sets color of the square. - */ - color : Viva.Graph.View._webglUtil.parseColor(color) - }; -}; - -/** - * Represents a model for image. - */ -Viva.Graph.View.webglImage = function (size, src) { return { /** - * Gets texture index where current image is placed.s + * Sets the collback that creates node representation or creates a new node + * presentation if builderCallbackOrNode is not a function. + * + * @param builderCallbackOrNode a callback function that accepts graph node + * as a parameter and must return an element representing this node. OR + * if it's not a function it's treated as a node to which DOM element should be created. + * + * @returns If builderCallbackOrNode is a valid callback function, instance of this is returned; + * Otherwise a node representation is returned for the passed parameter. */ - _texture : 0, + node : function (builderCallbackOrNode) { + if (builderCallbackOrNode && typeof builderCallbackOrNode !== "function") { + return nodeBuilder(builderCallbackOrNode); + } - /** - * Gets offset in the texture where current image is placed. - */ - _offset : 0, + nodeBuilder = builderCallbackOrNode; - /** - * Gets size of the square with the image. - */ - size : typeof size === 'number' ? size : 32, + return this; + }, /** - * Source of the image. If image is comming not from your domain - * certain origin restrictions applies. - * See http://www.khronos.org/registry/webgl/specs/latest/#4.2 for more details. + * Sets the collback that creates link representation or creates a new link + * presentation if builderCallbackOrLink is not a function. + * + * @param builderCallbackOrLink a callback function that accepts graph link + * as a parameter and must return an element representing this link. OR + * if it's not a function it's treated as a link to which DOM element should be created. + * + * @returns If builderCallbackOrLink is a valid callback function, instance of this is returned; + * Otherwise a link representation is returned for the passed parameter. */ - src : src - }; -};/** - * @fileOverview Defines a naive form of nodes for webglGraphics class. - * This form allows to change color of node. Shape of nodes is rectangular. - * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com - */ - -/** - * Defines simple UI for nodes in webgl renderer. Each node is rendered as square. Color and size can be changed. - */ -Viva.Graph.View.webglNodeProgram = function () { - var ATTRIBUTES_PER_PRIMITIVE = 4, // Primitive is point, x, y, size, color - // x, y, z - floats, color = uint. - BYTES_PER_NODE = 3 * Float32Array.BYTES_PER_ELEMENT + Uint32Array.BYTES_PER_ELEMENT, - nodesFS = [ - 'precision mediump float;', - 'varying vec4 color;', - - 'void main(void) {', - ' gl_FragColor = color;', - '}' - ].join('\n'), - nodesVS = [ - 'attribute vec3 a_vertexPos;', - 'attribute vec4 a_color;', - 'uniform vec2 u_screenSize;', - 'uniform mat4 u_transform;', - 'varying vec4 color;', - - 'void main(void) {', - ' gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);', - ' gl_PointSize = a_vertexPos.z * u_transform[0][0];', - ' color = a_color.abgr;', - '}' - ].join('\n'), - - program, - gl, - buffer, - locations, - utils, - storage = new ArrayBuffer(16 * BYTES_PER_NODE), - positions = new Float32Array(storage), - colors = new Uint32Array(storage), - nodesCount = 0, - width, - height, - transform, - sizeDirty, - - ensureEnoughStorage = function () { - if ((nodesCount + 1) * BYTES_PER_NODE >= storage.byteLength) { - // Every time we run out of space create new array twice bigger. - // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs - var extendedStorage = new ArrayBuffer(storage.byteLength * 2), - extendedPositions = new Float32Array(extendedStorage), - extendedColors = new Uint32Array(extendedStorage); - - extendedColors.set(colors); // should be enough to copy just one view. - positions = extendedPositions; - colors = extendedColors; - storage = extendedStorage; + link : function (builderCallbackOrLink) { + if (builderCallbackOrLink && typeof builderCallbackOrLink !== "function") { + return linkBuilder(builderCallbackOrLink); } - }; - - return { - load : function (glContext) { - gl = glContext; - utils = Viva.Graph.webgl(glContext); - program = utils.createProgram(nodesVS, nodesFS); - gl.useProgram(program); - locations = utils.getLocations(program, ['a_vertexPos', 'a_color', 'u_screenSize', 'u_transform']); - - gl.enableVertexAttribArray(locations.vertexPos); - gl.enableVertexAttribArray(locations.color); - - buffer = gl.createBuffer(); + linkBuilder = builderCallbackOrLink; + return this; }, /** - * Updates position of node in the buffer of nodes. - * - * @param idx - index of current node. - * @param pos - new position of the node. + * Default input manager listens to DOM events to process nodes drag-n-drop */ - position : function (nodeUI, pos) { - var idx = nodeUI.id; - - positions[idx * ATTRIBUTES_PER_PRIMITIVE] = pos.x; - positions[idx * ATTRIBUTES_PER_PRIMITIVE + 1] = pos.y; - positions[idx * ATTRIBUTES_PER_PRIMITIVE + 2] = nodeUI.size; + inputManager : Viva.Input.domInputManager, - colors[idx * ATTRIBUTES_PER_PRIMITIVE + 3] = nodeUI.color; + /** + * Sets translate operation that should be applied to all nodes and links. + */ + graphCenterChanged : function (x, y) { + offsetX = x; + offsetY = y; + updateTransform(); }, - updateTransform : function (newTransform) { - sizeDirty = true; - transform = newTransform; + translateRel : function (dx, dy) { + offsetX += dx; + offsetY += dy; + updateTransform(); }, - updateSize : function (w, h) { - width = w; - height = h; - sizeDirty = true; + scale : function (x, y) { + // TODO: implement me + return 1; }, - removeNode : function (node) { - if (nodesCount > 0) { nodesCount -= 1; } - - if (node.id < nodesCount && nodesCount > 0) { - // we can use colors as a 'view' into array array buffer. - utils.copyArrayPart(colors, node.id * ATTRIBUTES_PER_PRIMITIVE, nodesCount * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); - } - }, -/*jshint unused:false */ - createNode : function (node) { - ensureEnoughStorage(); - nodesCount += 1; + resetScale : function () { + // TODO: implement me + return this; }, - replaceProperties : function (replacedNode, newNode) {}, -/*jshint unused:true */ - - render : function () { - gl.useProgram(program); - gl.bindBuffer(gl.ARRAY_BUFFER, buffer); - gl.bufferData(gl.ARRAY_BUFFER, storage, gl.DYNAMIC_DRAW); - - if (sizeDirty) { - sizeDirty = false; - gl.uniformMatrix4fv(locations.transform, false, transform); - gl.uniform2f(locations.screenSize, width, height); - } - - gl.vertexAttribPointer(locations.vertexPos, 3, gl.FLOAT, false, ATTRIBUTES_PER_PRIMITIVE * Float32Array.BYTES_PER_ELEMENT, 0); - gl.vertexAttribPointer(locations.color, 4, gl.UNSIGNED_BYTE, true, ATTRIBUTES_PER_PRIMITIVE * Float32Array.BYTES_PER_ELEMENT, 3 * 4); - - gl.drawArrays(gl.POINTS, 0, nodesCount); - } - }; -}; -/** - * @fileOverview Defines a naive form of links for webglGraphics class. - * This form allows to change color of links. - * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com - */ - -/** - * Defines UI for links in webgl renderer. - */ -Viva.Graph.View.webglLinkProgram = function () { - var ATTRIBUTES_PER_PRIMITIVE = 6, // primitive is Line with two points. Each has x,y and color = 3 * 2 attributes. - BYTES_PER_LINK = 2 * (2 * Float32Array.BYTES_PER_ELEMENT + Uint32Array.BYTES_PER_ELEMENT), // two nodes * (x, y + color) - linksFS = [ - 'precision mediump float;', - 'varying vec4 color;', - 'void main(void) {', - ' gl_FragColor = color;', - '}' - ].join('\n'), - - linksVS = [ - 'attribute vec2 a_vertexPos;', - 'attribute vec4 a_color;', - - 'uniform vec2 u_screenSize;', - 'uniform mat4 u_transform;', - - 'varying vec4 color;', - - 'void main(void) {', - ' gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);', - ' color = a_color.abgr;', - '}' - ].join('\n'), - - program, - gl, - buffer, - utils, - locations, - linksCount = 0, - frontLinkId, // used to track z-index of links. - storage = new ArrayBuffer(16 * BYTES_PER_LINK), - positions = new Float32Array(storage), - colors = new Uint32Array(storage), - width, - height, - transform, - sizeDirty, - - ensureEnoughStorage = function () { - // TODO: this is a duplicate of webglNodeProgram code. Extract it to webgl.js - if ((linksCount+1)*BYTES_PER_LINK > storage.byteLength) { - // Every time we run out of space create new array twice bigger. - // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs - var extendedStorage = new ArrayBuffer(storage.byteLength * 2), - extendedPositions = new Float32Array(extendedStorage), - extendedColors = new Uint32Array(extendedStorage); - - extendedColors.set(colors); // should be enough to copy just one view. - positions = extendedPositions; - colors = extendedColors; - storage = extendedStorage; - } - }; - - return { - load : function (glContext) { - gl = glContext; - utils = Viva.Graph.webgl(glContext); - - program = utils.createProgram(linksVS, linksFS); - gl.useProgram(program); - locations = utils.getLocations(program, ['a_vertexPos', 'a_color', 'u_screenSize', 'u_transform']); - - gl.enableVertexAttribArray(locations.vertexPos); - gl.enableVertexAttribArray(locations.color); + /** + * Called every before renderer starts rendering. + */ + beginRender : function () {}, - buffer = gl.createBuffer(); + /** + * Called every time when renderer finishes one step of rendering. + */ + endRender : function () {}, + /** + * Allows to override default position setter for the node with a new + * function. newPlaceCallback(node, position) is function which + * is used by updateNode(). + */ + placeNode : function (newPlaceCallback) { + nodePositionCallback = newPlaceCallback; + return this; }, - position: function (linkUi, fromPos, toPos) { - var linkIdx = linkUi.id, - offset = linkIdx * ATTRIBUTES_PER_PRIMITIVE; - positions[offset] = fromPos.x; - positions[offset + 1] = fromPos.y; - colors[offset + 2] = linkUi.color; - - positions[offset + 3] = toPos.x; - positions[offset + 4] = toPos.y; - colors[offset + 5] = linkUi.color; + placeLink : function (newPlaceLinkCallback) { + linkPositionCallback = newPlaceLinkCallback; + return this; }, - createLink : function (ui) { - ensureEnoughStorage(); - - linksCount += 1; - frontLinkId = ui.id; + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * providers prepare to render. + */ + init : function (parentContainer) { + container = parentContainer; + updateTransform(); }, - removeLink : function (ui) { - if (linksCount > 0) { linksCount -= 1; } - // swap removed link with the last link. This will give us O(1) performance for links removal: - if (ui.id < linksCount && linksCount > 0) { - // using colors as a view to array buffer is okay here. - utils.copyArrayPart(colors, ui.id * ATTRIBUTES_PER_PRIMITIVE, linksCount * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render given link of the graph + * + * @param linkUI visual representation of the link created by link() execution. + */ + initLink : function (linkUI) { + if (container.childElementCount > 0) { + container.insertBefore(linkUI, container.firstChild); + } else { + container.appendChild(linkUI); } }, - updateTransform : function (newTransform) { - sizeDirty = true; - transform = newTransform; + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider remove link from rendering surface. + * + * @param linkUI visual representation of the link created by link() execution. + **/ + releaseLink : function (linkUI) { + container.removeChild(linkUI); }, - updateSize : function (w, h) { - width = w; - height = h; - sizeDirty = true; + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render given node of the graph. + * + * @param nodeUI visual representation of the node created by node() execution. + **/ + initNode : function (nodeUI) { + container.appendChild(nodeUI); }, - render : function () { - gl.useProgram(program); - gl.bindBuffer(gl.ARRAY_BUFFER, buffer); - gl.bufferData(gl.ARRAY_BUFFER, storage, gl.DYNAMIC_DRAW); - - if (sizeDirty) { - sizeDirty = false; - gl.uniformMatrix4fv(locations.transform, false, transform); - gl.uniform2f(locations.screenSize, width, height); - } - - gl.vertexAttribPointer(locations.vertexPos, 2, gl.FLOAT, false, 3 * Float32Array.BYTES_PER_ELEMENT, 0); - gl.vertexAttribPointer(locations.color, 4, gl.UNSIGNED_BYTE, true, 3 * Float32Array.BYTES_PER_ELEMENT, 2 * 4); - - gl.drawArrays(gl.LINES, 0, linksCount * 2); - - frontLinkId = linksCount - 1; + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider remove node from rendering surface. + * + * @param nodeUI visual representation of the node created by node() execution. + **/ + releaseNode : function (nodeUI) { + container.removeChild(nodeUI); }, - bringToFront : function (link) { - if (frontLinkId > link.id) { - utils.swapArrayPart(positions, link.id * ATTRIBUTES_PER_PRIMITIVE, frontLinkId * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); - } - if (frontLinkId > 0) { - frontLinkId -= 1; - } + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider place given node to recommended position pos {x, y}; + */ + updateNodePosition : function (node, pos) { + nodePositionCallback(node, pos); }, - getFrontLinkId : function () { - return frontLinkId; + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider place given link of the graph + */ + updateLinkPosition : function (link, fromPos, toPos) { + linkPositionCallback(link, fromPos, toPos); } }; }; +/** + * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + */ + +/** + * Simple wrapper over svg object model API, to shorten the usage syntax. + */ +Viva.Graph.svg = function (element) { + var svgns = "http://www.w3.org/2000/svg", + xlinkns = "http://www.w3.org/1999/xlink", + svgElement = element; + + if (typeof element === "string") { + svgElement = window.document.createElementNS(svgns, element); + } + + if (svgElement.vivagraphAugmented) { + return svgElement; + } + + svgElement.vivagraphAugmented = true; + + // Augment svg element (TODO: it's not safe - what if some function already exists on the prototype?): + + /** + * Gets an svg attribute from an element if value is not specified. + * OR sets a new value to the given attribute. + * + * @param name - svg attribute name; + * @param value - value to be set; + * + * @returns svg element if both name and value are specified; or value of the given attribute + * if value parameter is missing. + */ + svgElement.attr = function (name, value) { + if (arguments.length === 2) { + if (value !== null) { + svgElement.setAttributeNS(null, name, value); + } else { + svgElement.removeAttributeNS(null, name); + } + + return svgElement; + } + + return svgElement.getAttributeNS(null, name); + }; + + svgElement.append = function (element) { + var child = Viva.Graph.svg(element); + svgElement.appendChild(child); + return child; + }; + + svgElement.text = function (textContent) { + if (typeof textContent !== "undefined") { + svgElement.textContent = textContent; + return svgElement; + } + return svgElement.textContent; + }; + + svgElement.link = function (target) { + if (arguments.length) { + svgElement.setAttributeNS(xlinkns, "xlink:href", target); + return svgElement; + } + + return svgElement.getAttributeNS(xlinkns, "xlink:href"); + }; + + svgElement.children = function (selector) { + var wrappedChildren = [], + childrenCount = svgElement.childNodes.length, + i, + j; + + if (selector === undefined && svgElement.hasChildNodes()) { + for (i = 0; i < childrenCount; i++) { + wrappedChildren.push(Viva.Graph.svg(svgElement.childNodes[i])); + } + } else if (typeof selector === "string") { + var classSelector = (selector[0] === "."), + idSelector = (selector[0] === "#"), + tagSelector = !classSelector && !idSelector; + + for (i = 0; i < childrenCount; i++) { + var el = svgElement.childNodes[i]; + + // pass comments, text nodes etc. + if (el.nodeType === 1) { + var classes = el.attr("class"), + id = el.attr("id"), + tagName = el.nodeName; + + if (classSelector && classes) { + classes = classes.replace(/\s+/g, " ").split(" "); + for (j = 0; j < classes.length; j++) { + if (classSelector && classes[j] === selector.substr(1)) { + wrappedChildren.push(Viva.Graph.svg(el)); + break; + } + } + } else if (idSelector && id === selector.substr(1)) { + wrappedChildren.push(Viva.Graph.svg(el)); + break; + } else if (tagSelector && tagName === selector) { + wrappedChildren.push(Viva.Graph.svg(el)); + } + + wrappedChildren = wrappedChildren.concat(Viva.Graph.svg(el).children(selector)); + } + } + + if (idSelector && wrappedChildren.length === 1) { + return wrappedChildren[0]; + } + } + + return wrappedChildren; + }; + + return svgElement; +}; /** - * @fileOverview Defines an image nodes for webglGraphics class. - * Shape of nodes is sqare. + * @fileOverview Defines a graph renderer that uses SVG based drawings. * * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com */ -/** - * Single texture in the webglAtlas. - */ -Viva.Graph.View.Texture = function (size) { - this.canvas = window.document.createElement("canvas"); - this.ctx = this.canvas.getContext("2d"); - this.isDirty = false; - this.canvas.width = this.canvas.height = size; -}; +Viva.Graph.View = Viva.Graph.View || {}; /** - * My naive implementation of textures atlas. It allows clients to load - * multimple images into atlas and get canvas representing all of them. - * - * @param tilesPerTexture - indicates how many images can be loaded to one - * texture of the atlas. If number of loaded images exceeds this - * parameter a new canvas will be created. + * Performs svg-based graph rendering. This module does not perform + * layout, but only visualizes nodes and edeges of the graph. */ -Viva.Graph.View.webglAtlas = function (tilesPerTexture) { - var tilesPerRow = Math.sqrt(tilesPerTexture || 1024) << 0, - tileSize = tilesPerRow, - lastLoadedIdx = 1, - loadedImages = {}, - dirtyTimeoutId, - skipedDirty = 0, - textures = [], - trackedUrls = [], - that, - - isPowerOf2 = function (n) { - return (n & (n - 1)) === 0; - }, - createTexture = function () { - var texture = new Viva.Graph.View.Texture(tilesPerRow * tileSize); - textures.push(texture); - }, - getTileCoordinates = function (absolutePosition) { - var textureNumber = (absolutePosition / tilesPerTexture) << 0, - localTileNumber = (absolutePosition % tilesPerTexture), - row = (localTileNumber / tilesPerRow) << 0, - col = (localTileNumber % tilesPerRow); - - return {textureNumber : textureNumber, row : row, col: col}; - }, - markDirtyNow = function () { - that.isDirty = true; - skipedDirty = 0; - dirtyTimeoutId = null; - }, - markDirty = function () { - // delay this call, since it results in texture reload - if (dirtyTimeoutId) { - window.clearTimeout(dirtyTimeoutId); - skipedDirty += 1; - dirtyTimeoutId = null; - } - - if (skipedDirty > 10) { - markDirtyNow(); - } else { - dirtyTimeoutId = window.setTimeout(markDirtyNow, 400); - } +Viva.Graph.View.svgGraphics = function () { + var svgContainer, + svgRoot, + offsetX, + offsetY, + initCallback, + actualScale = 1, + allNodes = {}, + allLinks = {}, +/*jshint unused: false */ + nodeBuilder = function (node) { + return Viva.Graph.svg("rect") + .attr("width", 10) + .attr("height", 10) + .attr("fill", "#00a2e8"); }, - copy = function (from, to) { - var fromCanvas = textures[from.textureNumber].canvas, - toCtx = textures[to.textureNumber].ctx, - x = to.col * tileSize, - y = to.row * tileSize; - - toCtx.drawImage(fromCanvas, from.col * tileSize, from.row * tileSize, tileSize, tileSize, x, y, tileSize, tileSize); - textures[from.textureNumber].isDirty = true; - textures[to.textureNumber].isDirty = true; + nodePositionCallback = function (nodeUI, pos) { + // TODO: Remove magic 5. It should be halfo of the width or height of the node. + nodeUI.attr("x", pos.x - 5) + .attr("y", pos.y - 5); }, - drawAt = function (tileNumber, img, callback) { - var tilePosition = getTileCoordinates(tileNumber), - coordinates = { offset : tileNumber }; + linkBuilder = function (link) { + return Viva.Graph.svg("line") + .attr("stroke", "#999"); + }, - if (tilePosition.textureNumber >= textures.length) { - createTexture(); - } - var currentTexture = textures[tilePosition.textureNumber]; + linkPositionCallback = function (linkUI, fromPos, toPos) { + linkUI.attr("x1", fromPos.x) + .attr("y1", fromPos.y) + .attr("x2", toPos.x) + .attr("y2", toPos.y); + }, - currentTexture.ctx.drawImage(img, tilePosition.col * tileSize, tilePosition.row * tileSize, tileSize, tileSize); - trackedUrls[tileNumber] = img.src; + fireRescaled = function (graphics) { + // TODO: maybe we shall copy changes? + graphics.fire("rescaled"); + }, - loadedImages[img.src] = coordinates; - currentTexture.isDirty = true; + cachedPos = {x : 0, y: 0}, + cachedFromPos = {x : 0, y: 0}, + cachedToPos = {x : 0, y: 0}, - callback(coordinates); + updateTransform = function () { + if (svgContainer) { + var transform = "matrix(" + actualScale + ", 0, 0," + actualScale + "," + offsetX + "," + offsetY + ")"; + svgContainer.attr("transform", transform); + } }; - if (!isPowerOf2(tilesPerTexture)) { - throw "Tiles per texture should be power of two."; - } + svgRoot = createSvgRoot(); - // this is the return object - that = { - /** - * indicates whether atlas has changed texture in it. If true then - * some of the textures has isDirty flag set as well. - */ - isDirty : false, + var graphics = { + getNodeUI: function (nodeId) { + return allNodes[nodeId]; + }, + + getLinkUI: function (linkId) { + return allLinks[linkId]; + }, /** - * Clears any signs of atlas changes. + * Sets the callback that creates node representation. + * + * @param builderCallback a callback function that accepts graph node + * as a parameter and must return an element representing this node. + * + * @returns If builderCallbackOrNode is a valid callback function, instance of this is returned; + * Otherwise undefined value is returned */ - clearDirty : function () { - var i; - this.isDirty = false; - for (i = 0; i < textures.length; ++i) { - textures[i].isDirty = false; + node : function (builderCallback) { + if (typeof builderCallback !== "function") { + return; // todo: throw? this is not compatible with old versions } + + nodeBuilder = builderCallback; + + return this; }, /** - * Removes given url from colleciton of tiles in the atlas. + * Sets the callback that creates link representation + * + * @param builderCallback a callback function that accepts graph link + * as a parameter and must return an element representing this link. + * + * @returns If builderCallback is a valid callback function, instance of this is returned; + * Otherwise undefined value is returend. */ - remove : function (imgUrl) { - var coordinates = loadedImages[imgUrl]; - if (!coordinates) { return false; } - delete loadedImages[imgUrl]; - lastLoadedIdx -= 1; - - - if (lastLoadedIdx === coordinates.offset) { - return true; // Ignore if it's last image in the whole set. + link : function (builderCallback) { + if (typeof builderCallback !== "function") { + return; // todo: throw? this is not compatible with old versions } - var tileToRemove = getTileCoordinates(coordinates.offset), - lastTileInSet = getTileCoordinates(lastLoadedIdx); - - copy(lastTileInSet, tileToRemove); + linkBuilder = builderCallback; + return this; + }, - var replacedOffset = loadedImages[trackedUrls[lastLoadedIdx]]; - replacedOffset.offset = coordinates.offset; - trackedUrls[coordinates.offset] = trackedUrls[lastLoadedIdx]; + /** + * Allows to override default position setter for the node with a new + * function. newPlaceCallback(nodeUI, position, node) is function which + * is used by updateNodePosition(). + */ + placeNode : function (newPlaceCallback) { + nodePositionCallback = newPlaceCallback; + return this; + }, - markDirty(); - return true; + placeLink : function (newPlaceLinkCallback) { + linkPositionCallback = newPlaceLinkCallback; + return this; }, /** - * Gets all textures in the atlas. + * Called every before renderer starts rendering. */ - getTextures : function () { - return textures; // I trust you... - }, + beginRender : function () {}, /** - * Gets coordinates of the given image in the atlas. Coordinates is an object: - * {offset : int } - where offset is an absolute position of the image in the - * atlas. - * - * Absolute means it can be larger than tilesPerTexture parameter, and in that - * case clients should get next texture in getTextures() collection. + * Called every time when renderer finishes one step of rendering. */ - getCoordinates : function (imgUrl) { - return loadedImages[imgUrl]; + endRender : function () {}, + + /** + * Sets translate operation that should be applied to all nodes and links. + */ + graphCenterChanged : function (x, y) { + offsetX = x; + offsetY = y; + updateTransform(); }, /** - * Asynchronously Loads the image to the atlas. Cross-domain security - * limitation applies. + * Default input manager listens to DOM events to process nodes drag-n-drop */ - load : function (imgUrl, callback) { - if (loadedImages.hasOwnProperty(imgUrl)) { - callback(loadedImages[imgUrl]); - } else { - var img = new window.Image(), - imgId = lastLoadedIdx; - - lastLoadedIdx += 1; - img.crossOrigin = "anonymous"; - img.onload = function () { - markDirty(); - drawAt(imgId, img, callback); - }; + inputManager : Viva.Input.domInputManager, - img.src = imgUrl; - } - } - }; + translateRel : function (dx, dy) { + var p = svgRoot.createSVGPoint(), + t = svgContainer.getCTM(), + origin = svgRoot.createSVGPoint().matrixTransform(t.inverse()); - return that; -}; + p.x = dx; + p.y = dy; -/** - * Defines simple UI for nodes in webgl renderer. Each node is rendered as an image. - */ -Viva.Graph.View.webglImageNodeProgram = function () { - var ATTRIBUTES_PER_PRIMITIVE = 18, - nodesFS = [ - "precision mediump float;", - "varying vec4 color;", - "varying vec3 vTextureCoord;", - "uniform sampler2D u_sampler0;", - "uniform sampler2D u_sampler1;", - "uniform sampler2D u_sampler2;", - "uniform sampler2D u_sampler3;", - - "void main(void) {", - " if (vTextureCoord.z == 0.) {", - " gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);", - " } else if (vTextureCoord.z == 1.) {", - " gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);", - " } else if (vTextureCoord.z == 2.) {", - " gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);", - " } else if (vTextureCoord.z == 3.) {", - " gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);", - " } else { gl_FragColor = vec4(0, 1, 0, 1); }", - "}" - ].join("\n"), - - nodesVS = [ - "attribute vec2 a_vertexPos;", - - "attribute float a_customAttributes;", - "uniform vec2 u_screenSize;", - "uniform mat4 u_transform;", - "uniform float u_tilesPerTexture;", - "varying vec3 vTextureCoord;", - - "void main(void) {", - " gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);", - "float corner = mod(a_customAttributes, 4.);", - "float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);", - "float tilesPerRow = sqrt(u_tilesPerTexture);", - "float tileSize = 1./tilesPerRow;", - "float tileColumn = mod(tileIndex, tilesPerRow);", - "float tileRow = floor(tileIndex/tilesPerRow);", - - "if(corner == 0.0) {", - " vTextureCoord.xy = vec2(0, 1);", - "} else if(corner == 1.0) {", - " vTextureCoord.xy = vec2(1, 1);", - "} else if(corner == 2.0) {", - " vTextureCoord.xy = vec2(0, 0);", - "} else {", - " vTextureCoord.xy = vec2(1, 0);", - "}", - - "vTextureCoord *= tileSize;", - "vTextureCoord.x += tileColumn * tileSize;", - "vTextureCoord.y += tileRow * tileSize;", - "vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);", - "}" - ].join("\n"), - - tilesPerTexture = 1024, // TODO: Get based on max texture size - atlas; - - var program, - gl, - buffer, - utils, - locations, - nodesCount = 0, - nodes = new Float32Array(64), - width, - height, - transform, - sizeDirty, + p = p.matrixTransform(t.inverse()); + p.x = (p.x - origin.x) * t.a; + p.y = (p.y - origin.y) * t.d; - refreshTexture = function (texture, idx) { - if (texture.nativeObject) { - gl.deleteTexture(texture.nativeObject); - } + t.e += p.x; + t.f += p.y; + + var transform = "matrix(" + t.a + ", 0, 0," + t.d + "," + t.e + "," + t.f + ")"; + svgContainer.attr("transform", transform); + }, + + scale : function (scaleFactor, scrollPoint) { + var p = svgRoot.createSVGPoint(); + p.x = scrollPoint.x; + p.y = scrollPoint.y; + + p = p.matrixTransform(svgContainer.getCTM().inverse()); // translate to svg coordinates + + // Compute new scale matrix in current mouse position + var k = svgRoot.createSVGMatrix().translate(p.x, p.y).scale(scaleFactor).translate(-p.x, -p.y), + t = svgContainer.getCTM().multiply(k); - var nativeObject = gl.createTexture(); - gl.activeTexture(gl["TEXTURE" + idx]); - gl.bindTexture(gl.TEXTURE_2D, nativeObject); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.canvas); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST); + actualScale = t.a; + offsetX = t.e; + offsetY = t.f; + var transform = "matrix(" + t.a + ", 0, 0," + t.d + "," + t.e + "," + t.f + ")"; + svgContainer.attr("transform", transform); - gl.generateMipmap(gl.TEXTURE_2D); - gl.uniform1i(locations["sampler" + idx], idx); + fireRescaled(this); + return actualScale; + }, - texture.nativeObject = nativeObject; + resetScale : function () { + actualScale = 1; + var transform = "matrix(1, 0, 0, 1, 0, 0)"; + svgContainer.attr("transform", transform); + fireRescaled(this); + return this; }, - ensureAtlasTextureUpdated = function () { - if (atlas.isDirty) { - var textures = atlas.getTextures(), - i; - for (i = 0; i < textures.length; ++i) { - if (textures[i].isDirty || !textures[i].nativeObject) { - refreshTexture(textures[i], i); - } - } - - atlas.clearDirty(); + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render. + */ + init : function (container) { + container.appendChild(svgRoot); + updateTransform(); + // Notify the world if someoen waited for update. TODO: should send an event + if (typeof initCallback === "function") { + initCallback(svgRoot); } - }; - - return { - load : function (glContext) { - gl = glContext; - utils = Viva.Graph.webgl(glContext); - - atlas = new Viva.Graph.View.webglAtlas(tilesPerTexture); - - program = utils.createProgram(nodesVS, nodesFS); - gl.useProgram(program); - locations = utils.getLocations(program, ["a_vertexPos", "a_customAttributes", "u_screenSize", "u_transform", "u_sampler0", "u_sampler1", "u_sampler2", "u_sampler3", "u_tilesPerTexture"]); - - gl.uniform1f(locations.tilesPerTexture, tilesPerTexture); - - gl.enableVertexAttribArray(locations.vertexPos); - gl.enableVertexAttribArray(locations.customAttributes); + }, - buffer = gl.createBuffer(); + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider release occupied resources. + */ + release : function (container) { + if (svgRoot && container) { + container.removeChild(svgRoot); + } }, /** - * Updates position of current node in the buffer of nodes. + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render given link of the graph * - * @param idx - index of current node. - * @param pos - new position of the node. + * @param link - model of a link */ - position : function (nodeUI, pos) { - var idx = nodeUI.id * ATTRIBUTES_PER_PRIMITIVE; - nodes[idx] = pos.x - nodeUI.size; - nodes[idx + 1] = pos.y - nodeUI.size; - nodes[idx + 2] = nodeUI._offset * 4; - - nodes[idx + 3] = pos.x + nodeUI.size; - nodes[idx + 4] = pos.y - nodeUI.size; - nodes[idx + 5] = nodeUI._offset * 4 + 1; + addLink: function (link, pos) { + var linkUI = linkBuilder(link); + if (!linkUI) { return; } + linkUI.position = pos; + linkUI.link = link; + allLinks[link.id] = linkUI; + if (svgContainer.childElementCount > 0) { + svgContainer.insertBefore(linkUI, svgContainer.firstChild); + } else { + svgContainer.appendChild(linkUI); + } + return linkUI; + }, - nodes[idx + 6] = pos.x - nodeUI.size; - nodes[idx + 7] = pos.y + nodeUI.size; - nodes[idx + 8] = nodeUI._offset * 4 + 2; + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider remove link from rendering surface. + * + * @param linkUI visual representation of the link created by link() execution. + **/ + releaseLink : function (link) { + var linkUI = allLinks[link.id]; + if (linkUI) { + svgContainer.removeChild(linkUI); + delete allLinks[link.id]; + } + }, - nodes[idx + 9] = pos.x - nodeUI.size; - nodes[idx + 10] = pos.y + nodeUI.size; - nodes[idx + 11] = nodeUI._offset * 4 + 2; + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render given node of the graph. + * + * @param nodeUI visual representation of the node created by node() execution. + **/ + addNode : function (node, pos) { + var nodeUI = nodeBuilder(node); + if (!nodeUI) { + return; + } + nodeUI.position = pos; + nodeUI.node = node; + allNodes[node.id] = nodeUI; - nodes[idx + 12] = pos.x + nodeUI.size; - nodes[idx + 13] = pos.y - nodeUI.size; - nodes[idx + 14] = nodeUI._offset * 4 + 1; + svgContainer.appendChild(nodeUI); - nodes[idx + 15] = pos.x + nodeUI.size; - nodes[idx + 16] = pos.y + nodeUI.size; - nodes[idx + 17] = nodeUI._offset * 4 + 3; + return nodeUI; }, - createNode : function (ui) { - nodes = utils.extendArray(nodes, nodesCount, ATTRIBUTES_PER_PRIMITIVE); - nodesCount += 1; - - var coordinates = atlas.getCoordinates(ui.src); - if (coordinates) { - ui._offset = coordinates.offset; - } else { - ui._offset = 0; - // Image is not yet loaded into the atlas. Reload it: - atlas.load(ui.src, function (coordinates) { - ui._offset = coordinates.offset; - }); + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider remove node from rendering surface. + * + * @param node graph's node + **/ + releaseNode : function (node) { + var nodeUI = allNodes[node.id]; + if (nodeUI) { + svgContainer.removeChild(nodeUI); + delete allNodes[node.id]; } }, - removeNode : function (nodeUI) { - if (nodesCount > 0) { nodesCount -= 1; } - - if (nodeUI.id < nodesCount && nodesCount > 0) { - if (nodeUI.src) { - atlas.remove(nodeUI.src); + renderNodes : function () { + for (var key in allNodes) { + if (allNodes.hasOwnProperty(key)) { + var nodeUI = allNodes[key]; + cachedPos.x = nodeUI.position.x; + cachedPos.y = nodeUI.position.y; + nodePositionCallback(nodeUI, cachedPos, nodeUI.node); } - - utils.copyArrayPart(nodes, nodeUI.id * ATTRIBUTES_PER_PRIMITIVE, nodesCount * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); } }, - replaceProperties : function (replacedNode, newNode) { - newNode._offset = replacedNode._offset; + renderLinks : function () { + for (var key in allLinks) { + if (allLinks.hasOwnProperty(key)) { + var linkUI = allLinks[key]; + cachedFromPos.x = linkUI.position.from.x; + cachedFromPos.y = linkUI.position.from.y; + cachedToPos.x = linkUI.position.to.x; + cachedToPos.y = linkUI.position.to.y; + linkPositionCallback(linkUI, cachedFromPos, cachedToPos, linkUI.link); + } + } }, - updateTransform : function (newTransform) { - sizeDirty = true; - transform = newTransform; + /** + * Returns root element which hosts graphics. + */ + getGraphicsRoot : function (callbackWhenReady) { + // todo: should fire an event, instead of having this context. + if (typeof callbackWhenReady === "function") { + if (svgRoot) { + callbackWhenReady(svgRoot); + } else { + initCallback = callbackWhenReady; + } + } + return svgRoot; }, + /** + * Returns root svg element. + * + * Note: This is internal method specific to this renderer + */ + getSvgRoot : function () { + return svgRoot; + } + }; - updateSize : function (w, h) { - width = w; - height = h; - sizeDirty = true; - }, - render : function () { - gl.useProgram(program); - gl.bindBuffer(gl.ARRAY_BUFFER, buffer); - gl.bufferData(gl.ARRAY_BUFFER, nodes, gl.DYNAMIC_DRAW); + // Let graphics fire events before we return it to the caller. + Viva.Graph.Utils.events(graphics).extend(); - if (sizeDirty) { - sizeDirty = false; - gl.uniformMatrix4fv(locations.transform, false, transform); - gl.uniform2f(locations.screenSize, width, height); - } + return graphics; - gl.vertexAttribPointer(locations.vertexPos, 2, gl.FLOAT, false, 3 * Float32Array.BYTES_PER_ELEMENT, 0); - gl.vertexAttribPointer(locations.customAttributes, 1, gl.FLOAT, false, 3 * Float32Array.BYTES_PER_ELEMENT, 2 * 4); + function createSvgRoot() { + var svgRoot = Viva.Graph.svg("svg"); - ensureAtlasTextureUpdated(); + svgContainer = Viva.Graph.svg("g") + .attr("buffered-rendering", "dynamic"); - gl.drawArrays(gl.TRIANGLES, 0, nodesCount * 6); - } - }; + svgRoot.appendChild(svgContainer); + return svgRoot; + } +}; +/** + * @fileOverview I used this class to render links UI within + * node. Lesser SVG elements is proven to improve performance + * but I'm not happy with the code result here. Probably this class + * will be removed from future versions. + * + * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + */ + +Viva.Graph.View.svgNodeFactory = function (graph) { + var defaultColor = "#999", + geom = Viva.Graph.geom(), + + attachCustomContent = function (nodeUI) { + nodeUI.size = {w: 10, h: 10}; + nodeUI.append("rect") + .attr("width", nodeUI.size.w) + .attr("height", nodeUI.size.h) + .attr("stroke", "orange") + .attr("fill", "orange"); + }, + + nodeSize = function (nodeUI) { + return nodeUI.size; + }; + + + return { + node : function (node) { + var nodeUI = Viva.Graph.svg("g"); + + attachCustomContent(nodeUI, node); + nodeUI.nodeId = node.id; + return nodeUI; + }, + + link : function (link) { + var fromNode = graph.getNode(link.fromId), + nodeUI = fromNode && fromNode.ui; + + if (nodeUI && !nodeUI.linksContainer) { + var nodeLinks = Viva.Graph.svg("path") + .attr("stroke", defaultColor); + nodeUI.linksContainer = nodeLinks; + return nodeLinks; + } + + return null; + }, + + /** + * Sets a callback function for custom nodes contnet. + * @param conentCreator(nodeUI, node) - callback function which returns a node content UI. + * Image, for example. + * @param sizeProvider(nodeUI) - a callback function which accepts nodeUI returned by + * contentCreator and returns it"s custom rectangular size. + * + */ + customContent : function (contentCreator, sizeProvider) { + if (typeof contentCreator !== "function" || + typeof sizeProvider !== "function") { + throw "Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)"; + } + + attachCustomContent = contentCreator; + nodeSize = sizeProvider; + }, + + placeNode : function (nodeUI, fromNodePos) { + var linksPath = "", + fromNodeSize = nodeSize(nodeUI); + + graph.forEachLinkedNode(nodeUI.nodeId, function (linkedNode, link) { + if (!linkedNode.position || !linkedNode.ui) { + return; // not yet defined - ignore. + } + + if (linkedNode.ui === nodeUI) { + return; // incoming link - ignore; + } + if (link.fromId !== nodeUI.nodeId) { + return; // we process only outgoing links. + } + + var toNodeSize = nodeSize(linkedNode.ui), + toNodePos = linkedNode.position; + + var from = geom.intersectRect( + fromNodePos.x - fromNodeSize.w / 2, // left + fromNodePos.y - fromNodeSize.h / 2, // top + fromNodePos.x + fromNodeSize.w / 2, // right + fromNodePos.y + fromNodeSize.h / 2, // bottom + fromNodePos.x, + fromNodePos.y, + toNodePos.x, + toNodePos.y + ) || fromNodePos; + + var to = geom.intersectRect( + toNodePos.x - toNodeSize.w / 2, // left + toNodePos.y - toNodeSize.h / 2, // top + toNodePos.x + toNodeSize.w / 2, // right + toNodePos.y + toNodeSize.h / 2, // bottom + toNodePos.x, + toNodePos.y, + fromNodePos.x, + fromNodePos.y + ) || toNodePos; + + linksPath += "M" + Math.round(from.x) + " " + Math.round(from.y) + + "L" + Math.round(to.x) + " " + Math.round(to.y); + }); + + nodeUI.attr("transform", + "translate(" + (fromNodePos.x - fromNodeSize.w / 2) + ", " + + (fromNodePos.y - fromNodeSize.h / 2) + ")"); + if (linksPath !== "" && nodeUI.linksContainer) { + nodeUI.linksContainer.attr("d", linksPath); + } + } + + }; +}; +/** + * @fileOverview Utility functions for webgl rendering. + * + * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + */ + +Viva.Graph.webgl = function (gl) { + var createShader = function (shaderText, type) { + var shader = gl.createShader(type); + gl.shaderSource(shader, shaderText); + gl.compileShader(shader); + + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + var msg = gl.getShaderInfoLog(shader); + window.alert(msg); + throw msg; + } + + return shader; + }; + + return { + createProgram : function (vertexShaderSrc, fragmentShaderSrc) { + var program = gl.createProgram(), + vs = createShader(vertexShaderSrc, gl.VERTEX_SHADER), + fs = createShader(fragmentShaderSrc, gl.FRAGMENT_SHADER); + + gl.attachShader(program, vs); + gl.attachShader(program, fs); + gl.linkProgram(program); + + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { + var msg = gl.getShaderInfoLog(program); + window.alert(msg); + throw msg; + } + + return program; + }, + + extendArray : function (buffer, itemsInBuffer, elementsPerItem) { + if ((itemsInBuffer + 1) * elementsPerItem > buffer.length) { + // Every time we run out of space create new array twice bigger. + // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs + var extendedArray = new Float32Array(buffer.length * elementsPerItem * 2); + extendedArray.set(buffer); + + return extendedArray; + } + + return buffer; + }, + + copyArrayPart : function (array, to, from, elementsCount) { + var i; + for (i = 0; i < elementsCount; ++i) { + array[to + i] = array[from + i]; + } + }, + + swapArrayPart : function (array, from, to, elementsCount) { + var i; + for (i = 0; i < elementsCount; ++i) { + var tmp = array[from + i]; + array[from + i] = array[to + i]; + array[to + i] = tmp; + } + }, + + getLocations : function (program, uniformOrAttributeNames) { + var foundLocations = {}, + i; + for (i = 0; i < uniformOrAttributeNames.length; ++i) { + var name = uniformOrAttributeNames[i], + location = -1; + if (name.indexOf("a_") === 0) { + location = gl.getAttribLocation(program, name); + if (location === -1) { + throw "Program doesn't have required attribute: " + name; + } + + foundLocations[name.slice(2)] = location; + } else if (name.indexOf("u_") === 0) { + location = gl.getUniformLocation(program, name); + if (location === null) { + throw "Program doesn't have required uniform: " + name; + } + + foundLocations[name.slice(2)] = location; + } else { + throw "Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'"; + } + } + + return foundLocations; + }, + + context : gl + }; +}; +/** + * @fileOverview Defines a model objects to represents graph rendering + * primitives in webglGraphics. + * + * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + */ + +Viva.Graph.View.WebglUtils = function () { }; + +/** + * Parses various color strings and returns color value used in webgl shaders. + */ +Viva.Graph.View.WebglUtils.prototype.parseColor = function (color) { + var parsedColor = 0x009ee8ff; + + if (typeof color === 'string' && color) { + if (color.length === 4) { // #rgb + color = color.replace(/([^#])/g, '$1$1'); // duplicate each letter except first #. + } + if (color.length === 9) { // #rrggbbaa + parsedColor = parseInt(color.substr(1), 16); + } else if (color.length === 7) { // or #rrggbb. + parsedColor = (parseInt(color.substr(1), 16) << 8) | 0xff; + } else { + throw 'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: ' + color; + } + } else if (typeof color === 'number') { + parsedColor = color; + } + + return parsedColor; +}; + +Viva.Graph.View._webglUtil = new Viva.Graph.View.WebglUtils(); // reuse this instance internally. + +/** + * Defines a webgl line. This class has no rendering logic at all, + * it's just passed to corresponding shader and the shader should + * figure out how to render it. + * + * @see Viva.Graph.View.webglLinkShader.position + */ +Viva.Graph.View.webglLine = function (color) { + return { + /** + * Gets or sets color of the line. If you set this property externally + * make sure it always come as integer of 0xRRGGBBAA format + */ + color : Viva.Graph.View._webglUtil.parseColor(color) + }; +}; + +/** + * Can be used as a callback in the webglGraphics.node() function, to + * create a custom looking node. + * + * @param size - size of the node in pixels. + * @param color - color of the node in '#rrggbbaa' or '#rgb' format. + */ +Viva.Graph.View.webglSquare = function (size, color) { + return { + /** + * Gets or sets size of the sqare side. + */ + size : typeof size === 'number' ? size : 10, + + /** + * Gets or sets color of the square. + */ + color : Viva.Graph.View._webglUtil.parseColor(color) + }; +}; + +/** + * Represents a model for image. + */ +Viva.Graph.View.webglImage = function (size, src) { + return { + /** + * Gets texture index where current image is placed.s + */ + _texture : 0, + + /** + * Gets offset in the texture where current image is placed. + */ + _offset : 0, + + /** + * Gets size of the square with the image. + */ + size : typeof size === 'number' ? size : 32, + + /** + * Source of the image. If image is comming not from your domain + * certain origin restrictions applies. + * See http://www.khronos.org/registry/webgl/specs/latest/#4.2 for more details. + */ + src : src + }; +};/** + * @fileOverview Defines a naive form of nodes for webglGraphics class. + * This form allows to change color of node. Shape of nodes is rectangular. + * + * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + */ + +/** + * Defines simple UI for nodes in webgl renderer. Each node is rendered as square. Color and size can be changed. + */ +Viva.Graph.View.webglNodeProgram = function () { + var ATTRIBUTES_PER_PRIMITIVE = 4, // Primitive is point, x, y, size, color + // x, y, z - floats, color = uint. + BYTES_PER_NODE = 3 * Float32Array.BYTES_PER_ELEMENT + Uint32Array.BYTES_PER_ELEMENT, + nodesFS = [ + 'precision mediump float;', + 'varying vec4 color;', + + 'void main(void) {', + ' gl_FragColor = color;', + '}' + ].join('\n'), + nodesVS = [ + 'attribute vec3 a_vertexPos;', + 'attribute vec4 a_color;', + 'uniform vec2 u_screenSize;', + 'uniform mat4 u_transform;', + 'varying vec4 color;', + + 'void main(void) {', + ' gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);', + ' gl_PointSize = a_vertexPos.z * u_transform[0][0];', + ' color = a_color.abgr;', + '}' + ].join('\n'), + + program, + gl, + buffer, + locations, + utils, + storage = new ArrayBuffer(16 * BYTES_PER_NODE), + positions = new Float32Array(storage), + colors = new Uint32Array(storage), + nodesCount = 0, + width, + height, + transform, + sizeDirty, + + ensureEnoughStorage = function () { + if ((nodesCount + 1) * BYTES_PER_NODE >= storage.byteLength) { + // Every time we run out of space create new array twice bigger. + // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs + var extendedStorage = new ArrayBuffer(storage.byteLength * 2), + extendedPositions = new Float32Array(extendedStorage), + extendedColors = new Uint32Array(extendedStorage); + + extendedColors.set(colors); // should be enough to copy just one view. + positions = extendedPositions; + colors = extendedColors; + storage = extendedStorage; + } + }; + + return { + load : function (glContext) { + gl = glContext; + utils = Viva.Graph.webgl(glContext); + + program = utils.createProgram(nodesVS, nodesFS); + gl.useProgram(program); + locations = utils.getLocations(program, ['a_vertexPos', 'a_color', 'u_screenSize', 'u_transform']); + + gl.enableVertexAttribArray(locations.vertexPos); + gl.enableVertexAttribArray(locations.color); + + buffer = gl.createBuffer(); + }, + + /** + * Updates position of node in the buffer of nodes. + * + * @param idx - index of current node. + * @param pos - new position of the node. + */ + position : function (nodeUI, pos) { + var idx = nodeUI.id; + + positions[idx * ATTRIBUTES_PER_PRIMITIVE] = pos.x; + positions[idx * ATTRIBUTES_PER_PRIMITIVE + 1] = pos.y; + positions[idx * ATTRIBUTES_PER_PRIMITIVE + 2] = nodeUI.size; + + colors[idx * ATTRIBUTES_PER_PRIMITIVE + 3] = nodeUI.color; + }, + + updateTransform : function (newTransform) { + sizeDirty = true; + transform = newTransform; + }, + + updateSize : function (w, h) { + width = w; + height = h; + sizeDirty = true; + }, + + removeNode : function (node) { + if (nodesCount > 0) { nodesCount -= 1; } + + if (node.id < nodesCount && nodesCount > 0) { + // we can use colors as a 'view' into array array buffer. + utils.copyArrayPart(colors, node.id * ATTRIBUTES_PER_PRIMITIVE, nodesCount * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); + } + }, +/*jshint unused:false */ + createNode : function (node) { + ensureEnoughStorage(); + nodesCount += 1; + }, + + replaceProperties : function (replacedNode, newNode) {}, +/*jshint unused:true */ + + render : function () { + gl.useProgram(program); + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData(gl.ARRAY_BUFFER, storage, gl.DYNAMIC_DRAW); + + if (sizeDirty) { + sizeDirty = false; + gl.uniformMatrix4fv(locations.transform, false, transform); + gl.uniform2f(locations.screenSize, width, height); + } + + gl.vertexAttribPointer(locations.vertexPos, 3, gl.FLOAT, false, ATTRIBUTES_PER_PRIMITIVE * Float32Array.BYTES_PER_ELEMENT, 0); + gl.vertexAttribPointer(locations.color, 4, gl.UNSIGNED_BYTE, true, ATTRIBUTES_PER_PRIMITIVE * Float32Array.BYTES_PER_ELEMENT, 3 * 4); + + gl.drawArrays(gl.POINTS, 0, nodesCount); + } + }; +}; +/** + * @fileOverview Defines a naive form of links for webglGraphics class. + * This form allows to change color of links. + * + * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + */ + +/** + * Defines UI for links in webgl renderer. + */ +Viva.Graph.View.webglLinkProgram = function () { + var ATTRIBUTES_PER_PRIMITIVE = 6, // primitive is Line with two points. Each has x,y and color = 3 * 2 attributes. + BYTES_PER_LINK = 2 * (2 * Float32Array.BYTES_PER_ELEMENT + Uint32Array.BYTES_PER_ELEMENT), // two nodes * (x, y + color) + linksFS = [ + 'precision mediump float;', + 'varying vec4 color;', + 'void main(void) {', + ' gl_FragColor = color;', + '}' + ].join('\n'), + + linksVS = [ + 'attribute vec2 a_vertexPos;', + 'attribute vec4 a_color;', + + 'uniform vec2 u_screenSize;', + 'uniform mat4 u_transform;', + + 'varying vec4 color;', + + 'void main(void) {', + ' gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);', + ' color = a_color.abgr;', + '}' + ].join('\n'), + + program, + gl, + buffer, + utils, + locations, + linksCount = 0, + frontLinkId, // used to track z-index of links. + storage = new ArrayBuffer(16 * BYTES_PER_LINK), + positions = new Float32Array(storage), + colors = new Uint32Array(storage), + width, + height, + transform, + sizeDirty, + + ensureEnoughStorage = function () { + // TODO: this is a duplicate of webglNodeProgram code. Extract it to webgl.js + if ((linksCount+1)*BYTES_PER_LINK > storage.byteLength) { + // Every time we run out of space create new array twice bigger. + // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs + var extendedStorage = new ArrayBuffer(storage.byteLength * 2), + extendedPositions = new Float32Array(extendedStorage), + extendedColors = new Uint32Array(extendedStorage); + + extendedColors.set(colors); // should be enough to copy just one view. + positions = extendedPositions; + colors = extendedColors; + storage = extendedStorage; + } + }; + + return { + load : function (glContext) { + gl = glContext; + utils = Viva.Graph.webgl(glContext); + + program = utils.createProgram(linksVS, linksFS); + gl.useProgram(program); + locations = utils.getLocations(program, ['a_vertexPos', 'a_color', 'u_screenSize', 'u_transform']); + + gl.enableVertexAttribArray(locations.vertexPos); + gl.enableVertexAttribArray(locations.color); + + buffer = gl.createBuffer(); + }, + + position: function (linkUi, fromPos, toPos) { + var linkIdx = linkUi.id, + offset = linkIdx * ATTRIBUTES_PER_PRIMITIVE; + positions[offset] = fromPos.x; + positions[offset + 1] = fromPos.y; + colors[offset + 2] = linkUi.color; + + positions[offset + 3] = toPos.x; + positions[offset + 4] = toPos.y; + colors[offset + 5] = linkUi.color; + }, + + createLink : function (ui) { + ensureEnoughStorage(); + + linksCount += 1; + frontLinkId = ui.id; + }, + + removeLink : function (ui) { + if (linksCount > 0) { linksCount -= 1; } + // swap removed link with the last link. This will give us O(1) performance for links removal: + if (ui.id < linksCount && linksCount > 0) { + // using colors as a view to array buffer is okay here. + utils.copyArrayPart(colors, ui.id * ATTRIBUTES_PER_PRIMITIVE, linksCount * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); + } + }, + + updateTransform : function (newTransform) { + sizeDirty = true; + transform = newTransform; + }, + + updateSize : function (w, h) { + width = w; + height = h; + sizeDirty = true; + }, + + render : function () { + gl.useProgram(program); + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData(gl.ARRAY_BUFFER, storage, gl.DYNAMIC_DRAW); + + if (sizeDirty) { + sizeDirty = false; + gl.uniformMatrix4fv(locations.transform, false, transform); + gl.uniform2f(locations.screenSize, width, height); + } + + gl.vertexAttribPointer(locations.vertexPos, 2, gl.FLOAT, false, 3 * Float32Array.BYTES_PER_ELEMENT, 0); + gl.vertexAttribPointer(locations.color, 4, gl.UNSIGNED_BYTE, true, 3 * Float32Array.BYTES_PER_ELEMENT, 2 * 4); + + gl.drawArrays(gl.LINES, 0, linksCount * 2); + + frontLinkId = linksCount - 1; + }, + + bringToFront : function (link) { + if (frontLinkId > link.id) { + utils.swapArrayPart(positions, link.id * ATTRIBUTES_PER_PRIMITIVE, frontLinkId * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); + } + if (frontLinkId > 0) { + frontLinkId -= 1; + } + }, + + getFrontLinkId : function () { + return frontLinkId; + } + }; +}; +/** + * @fileOverview Defines an image nodes for webglGraphics class. + * Shape of nodes is sqare. + * + * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + */ + +/** + * Single texture in the webglAtlas. + */ +Viva.Graph.View.Texture = function (size) { + this.canvas = window.document.createElement("canvas"); + this.ctx = this.canvas.getContext("2d"); + this.isDirty = false; + this.canvas.width = this.canvas.height = size; +}; + +/** + * My naive implementation of textures atlas. It allows clients to load + * multimple images into atlas and get canvas representing all of them. + * + * @param tilesPerTexture - indicates how many images can be loaded to one + * texture of the atlas. If number of loaded images exceeds this + * parameter a new canvas will be created. + */ +Viva.Graph.View.webglAtlas = function (tilesPerTexture) { + var tilesPerRow = Math.sqrt(tilesPerTexture || 1024) << 0, + tileSize = tilesPerRow, + lastLoadedIdx = 1, + loadedImages = {}, + dirtyTimeoutId, + skipedDirty = 0, + textures = [], + trackedUrls = [], + that, + + isPowerOf2 = function (n) { + return (n & (n - 1)) === 0; + }, + createTexture = function () { + var texture = new Viva.Graph.View.Texture(tilesPerRow * tileSize); + textures.push(texture); + }, + getTileCoordinates = function (absolutePosition) { + var textureNumber = (absolutePosition / tilesPerTexture) << 0, + localTileNumber = (absolutePosition % tilesPerTexture), + row = (localTileNumber / tilesPerRow) << 0, + col = (localTileNumber % tilesPerRow); + + return {textureNumber : textureNumber, row : row, col: col}; + }, + markDirtyNow = function () { + that.isDirty = true; + skipedDirty = 0; + dirtyTimeoutId = null; + }, + markDirty = function () { + // delay this call, since it results in texture reload + if (dirtyTimeoutId) { + window.clearTimeout(dirtyTimeoutId); + skipedDirty += 1; + dirtyTimeoutId = null; + } + + if (skipedDirty > 10) { + markDirtyNow(); + } else { + dirtyTimeoutId = window.setTimeout(markDirtyNow, 400); + } + }, + + copy = function (from, to) { + var fromCanvas = textures[from.textureNumber].canvas, + toCtx = textures[to.textureNumber].ctx, + x = to.col * tileSize, + y = to.row * tileSize; + + toCtx.drawImage(fromCanvas, from.col * tileSize, from.row * tileSize, tileSize, tileSize, x, y, tileSize, tileSize); + textures[from.textureNumber].isDirty = true; + textures[to.textureNumber].isDirty = true; + }, + + drawAt = function (tileNumber, img, callback) { + var tilePosition = getTileCoordinates(tileNumber), + coordinates = { offset : tileNumber }; + + if (tilePosition.textureNumber >= textures.length) { + createTexture(); + } + var currentTexture = textures[tilePosition.textureNumber]; + + currentTexture.ctx.drawImage(img, tilePosition.col * tileSize, tilePosition.row * tileSize, tileSize, tileSize); + trackedUrls[tileNumber] = img.src; + + loadedImages[img.src] = coordinates; + currentTexture.isDirty = true; + + callback(coordinates); + }; + + if (!isPowerOf2(tilesPerTexture)) { + throw "Tiles per texture should be power of two."; + } + + // this is the return object + that = { + /** + * indicates whether atlas has changed texture in it. If true then + * some of the textures has isDirty flag set as well. + */ + isDirty : false, + + /** + * Clears any signs of atlas changes. + */ + clearDirty : function () { + var i; + this.isDirty = false; + for (i = 0; i < textures.length; ++i) { + textures[i].isDirty = false; + } + }, + + /** + * Removes given url from colleciton of tiles in the atlas. + */ + remove : function (imgUrl) { + var coordinates = loadedImages[imgUrl]; + if (!coordinates) { return false; } + delete loadedImages[imgUrl]; + lastLoadedIdx -= 1; + + + if (lastLoadedIdx === coordinates.offset) { + return true; // Ignore if it's last image in the whole set. + } + + var tileToRemove = getTileCoordinates(coordinates.offset), + lastTileInSet = getTileCoordinates(lastLoadedIdx); + + copy(lastTileInSet, tileToRemove); + + var replacedOffset = loadedImages[trackedUrls[lastLoadedIdx]]; + replacedOffset.offset = coordinates.offset; + trackedUrls[coordinates.offset] = trackedUrls[lastLoadedIdx]; + + markDirty(); + return true; + }, + + /** + * Gets all textures in the atlas. + */ + getTextures : function () { + return textures; // I trust you... + }, + + /** + * Gets coordinates of the given image in the atlas. Coordinates is an object: + * {offset : int } - where offset is an absolute position of the image in the + * atlas. + * + * Absolute means it can be larger than tilesPerTexture parameter, and in that + * case clients should get next texture in getTextures() collection. + */ + getCoordinates : function (imgUrl) { + return loadedImages[imgUrl]; + }, + + /** + * Asynchronously Loads the image to the atlas. Cross-domain security + * limitation applies. + */ + load : function (imgUrl, callback) { + if (loadedImages.hasOwnProperty(imgUrl)) { + callback(loadedImages[imgUrl]); + } else { + var img = new window.Image(), + imgId = lastLoadedIdx; + + lastLoadedIdx += 1; + img.crossOrigin = "anonymous"; + img.onload = function () { + markDirty(); + drawAt(imgId, img, callback); + }; + + img.src = imgUrl; + } + } + }; + + return that; +}; + +/** + * Defines simple UI for nodes in webgl renderer. Each node is rendered as an image. + */ +Viva.Graph.View.webglImageNodeProgram = function () { + var ATTRIBUTES_PER_PRIMITIVE = 18, + nodesFS = [ + "precision mediump float;", + "varying vec4 color;", + "varying vec3 vTextureCoord;", + "uniform sampler2D u_sampler0;", + "uniform sampler2D u_sampler1;", + "uniform sampler2D u_sampler2;", + "uniform sampler2D u_sampler3;", + + "void main(void) {", + " if (vTextureCoord.z == 0.) {", + " gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);", + " } else if (vTextureCoord.z == 1.) {", + " gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);", + " } else if (vTextureCoord.z == 2.) {", + " gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);", + " } else if (vTextureCoord.z == 3.) {", + " gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);", + " } else { gl_FragColor = vec4(0, 1, 0, 1); }", + "}" + ].join("\n"), + + nodesVS = [ + "attribute vec2 a_vertexPos;", + + "attribute float a_customAttributes;", + "uniform vec2 u_screenSize;", + "uniform mat4 u_transform;", + "uniform float u_tilesPerTexture;", + "varying vec3 vTextureCoord;", + + "void main(void) {", + " gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);", + "float corner = mod(a_customAttributes, 4.);", + "float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);", + "float tilesPerRow = sqrt(u_tilesPerTexture);", + "float tileSize = 1./tilesPerRow;", + "float tileColumn = mod(tileIndex, tilesPerRow);", + "float tileRow = floor(tileIndex/tilesPerRow);", + + "if(corner == 0.0) {", + " vTextureCoord.xy = vec2(0, 1);", + "} else if(corner == 1.0) {", + " vTextureCoord.xy = vec2(1, 1);", + "} else if(corner == 2.0) {", + " vTextureCoord.xy = vec2(0, 0);", + "} else {", + " vTextureCoord.xy = vec2(1, 0);", + "}", + + "vTextureCoord *= tileSize;", + "vTextureCoord.x += tileColumn * tileSize;", + "vTextureCoord.y += tileRow * tileSize;", + "vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);", + "}" + ].join("\n"), + + tilesPerTexture = 1024, // TODO: Get based on max texture size + atlas; + + var program, + gl, + buffer, + utils, + locations, + nodesCount = 0, + nodes = new Float32Array(64), + width, + height, + transform, + sizeDirty, + + refreshTexture = function (texture, idx) { + if (texture.nativeObject) { + gl.deleteTexture(texture.nativeObject); + } + + var nativeObject = gl.createTexture(); + gl.activeTexture(gl["TEXTURE" + idx]); + gl.bindTexture(gl.TEXTURE_2D, nativeObject); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.canvas); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST); + + gl.generateMipmap(gl.TEXTURE_2D); + gl.uniform1i(locations["sampler" + idx], idx); + + texture.nativeObject = nativeObject; + }, + + ensureAtlasTextureUpdated = function () { + if (atlas.isDirty) { + var textures = atlas.getTextures(), + i; + for (i = 0; i < textures.length; ++i) { + if (textures[i].isDirty || !textures[i].nativeObject) { + refreshTexture(textures[i], i); + } + } + + atlas.clearDirty(); + } + }; + + return { + load : function (glContext) { + gl = glContext; + utils = Viva.Graph.webgl(glContext); + + atlas = new Viva.Graph.View.webglAtlas(tilesPerTexture); + + program = utils.createProgram(nodesVS, nodesFS); + gl.useProgram(program); + locations = utils.getLocations(program, ["a_vertexPos", "a_customAttributes", "u_screenSize", "u_transform", "u_sampler0", "u_sampler1", "u_sampler2", "u_sampler3", "u_tilesPerTexture"]); + + gl.uniform1f(locations.tilesPerTexture, tilesPerTexture); + + gl.enableVertexAttribArray(locations.vertexPos); + gl.enableVertexAttribArray(locations.customAttributes); + + buffer = gl.createBuffer(); + }, + + /** + * Updates position of current node in the buffer of nodes. + * + * @param idx - index of current node. + * @param pos - new position of the node. + */ + position : function (nodeUI, pos) { + var idx = nodeUI.id * ATTRIBUTES_PER_PRIMITIVE; + nodes[idx] = pos.x - nodeUI.size; + nodes[idx + 1] = pos.y - nodeUI.size; + nodes[idx + 2] = nodeUI._offset * 4; + + nodes[idx + 3] = pos.x + nodeUI.size; + nodes[idx + 4] = pos.y - nodeUI.size; + nodes[idx + 5] = nodeUI._offset * 4 + 1; + + nodes[idx + 6] = pos.x - nodeUI.size; + nodes[idx + 7] = pos.y + nodeUI.size; + nodes[idx + 8] = nodeUI._offset * 4 + 2; + + nodes[idx + 9] = pos.x - nodeUI.size; + nodes[idx + 10] = pos.y + nodeUI.size; + nodes[idx + 11] = nodeUI._offset * 4 + 2; + + nodes[idx + 12] = pos.x + nodeUI.size; + nodes[idx + 13] = pos.y - nodeUI.size; + nodes[idx + 14] = nodeUI._offset * 4 + 1; + + nodes[idx + 15] = pos.x + nodeUI.size; + nodes[idx + 16] = pos.y + nodeUI.size; + nodes[idx + 17] = nodeUI._offset * 4 + 3; + }, + + createNode : function (ui) { + nodes = utils.extendArray(nodes, nodesCount, ATTRIBUTES_PER_PRIMITIVE); + nodesCount += 1; + + var coordinates = atlas.getCoordinates(ui.src); + if (coordinates) { + ui._offset = coordinates.offset; + } else { + ui._offset = 0; + // Image is not yet loaded into the atlas. Reload it: + atlas.load(ui.src, function (coordinates) { + ui._offset = coordinates.offset; + }); + } + }, + + removeNode : function (nodeUI) { + if (nodesCount > 0) { nodesCount -= 1; } + + if (nodeUI.id < nodesCount && nodesCount > 0) { + if (nodeUI.src) { + atlas.remove(nodeUI.src); + } + + utils.copyArrayPart(nodes, nodeUI.id * ATTRIBUTES_PER_PRIMITIVE, nodesCount * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); + } + }, + + replaceProperties : function (replacedNode, newNode) { + newNode._offset = replacedNode._offset; + }, + + updateTransform : function (newTransform) { + sizeDirty = true; + transform = newTransform; + }, + + updateSize : function (w, h) { + width = w; + height = h; + sizeDirty = true; + }, + + render : function () { + gl.useProgram(program); + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData(gl.ARRAY_BUFFER, nodes, gl.DYNAMIC_DRAW); + + if (sizeDirty) { + sizeDirty = false; + gl.uniformMatrix4fv(locations.transform, false, transform); + gl.uniform2f(locations.screenSize, width, height); + } + + gl.vertexAttribPointer(locations.vertexPos, 2, gl.FLOAT, false, 3 * Float32Array.BYTES_PER_ELEMENT, 0); + gl.vertexAttribPointer(locations.customAttributes, 1, gl.FLOAT, false, 3 * Float32Array.BYTES_PER_ELEMENT, 2 * 4); + + ensureAtlasTextureUpdated(); + + gl.drawArrays(gl.TRIANGLES, 0, nodesCount * 6); + } + }; };/** * @fileOverview Defines a graph renderer that uses WebGL based drawings. * @@ -5845,7 +5852,7 @@ Viva.Graph.View = Viva.Graph.View || {}; * * @param options - to customize graphics behavior. Currently supported parameter * enableBlending - true by default, allows to use transparency in node/links colors. - * preserveDrawingBuffer - false by default, tells webgl to preserve drawing buffer. + * preserveDrawingBuffer - false by default, tells webgl to preserve drawing buffer. * See https://www.khronos.org/registry/webgl/specs/1.0/#5.2 */ @@ -5920,6 +5927,8 @@ Viva.Graph.View.webglGraphics = function (options) { graphics.fire("rescaled"); }; + graphicsRoot = window.document.createElement("canvas"); + var graphics = { getLinkUI: function (linkId) { return allLinks[linkId]; @@ -5991,7 +6000,7 @@ Viva.Graph.View.webglGraphics = function (options) { * Called every time before renderer starts rendering. */ beginRender : function () { - // this function could be replaced by this.init, + // this function could be replaced by this.init, // based on user options. }, @@ -6126,7 +6135,6 @@ Viva.Graph.View.webglGraphics = function (options) { container = c; - graphicsRoot = window.document.createElement("canvas"); updateSize(); resetScaleInternal(); container.appendChild(graphicsRoot); @@ -6345,7 +6353,7 @@ Viva.Graph.View.webglGraphics = function (options) { getNodeAtClientPos: function (clientPos, preciseCheck) { if (typeof preciseCheck !== "function") { // we don't know anything about your node structure here :( - // potentially this could be delegated to node program, but for + // potentially this could be delegated to node program, but for // right now, we are giving up if you don't pass boundary check // callback. It answers to a question is nodeUI covers (x, y) return null; @@ -6368,286 +6376,286 @@ Viva.Graph.View.webglGraphics = function (options) { return graphics; }; -/** - * Monitors graph-related mouse input in webgl graphics and notifies subscribers. - * - * @param {Viva.Graph.View.webglGraphics} webglGraphics - */ -Viva.Graph.webglInputEvents = function (webglGraphics) { - if (webglGraphics.webglInputEvents) { - // Don't listen twice, if we are already attached to this graphics: - return webglGraphics.webglInputEvents; - } - - var preciseCheck = function (nodeUI, x, y) { - if (nodeUI && nodeUI.size) { - var pos = nodeUI.position, - half = nodeUI.size; - - return pos.x - half < x && x < pos.x + half && - pos.y - half < y && y < pos.y + half; - } - - return true; - }, - getNodeAtClientPos = function (pos) { - return webglGraphics.getNodeAtClientPos(pos, preciseCheck); - }, - mouseCapturedNode = null, - - mouseEnterCallback = [], - mouseLeaveCallback = [], - mouseDownCallback = [], - mouseUpCallback = [], - mouseMoveCallback = [], - clickCallback = [], - dblClickCallback = [], - documentEvents = Viva.Graph.Utils.events(window.document), - prevSelectStart, - boundRect, - - stopPropagation = function (e) { - if (e.stopPropagation) { - e.stopPropagation(); - } else { - e.cancelBubble = true; - } - }, - - handleDisabledEvent = function (e) { - stopPropagation(e); - return false; - }, - - invoke = function (callbacksChain, args) { - var i, stopPropagation; - for (i = 0; i < callbacksChain.length; i += 1) { - stopPropagation = callbacksChain[i].apply(undefined, args); - if (stopPropagation) { return true; } - } - }, - - startListen = function (root) { - var pos = {x : 0, y : 0}, - lastFound = null, - lastClickTime = +new Date(), - - handleMouseMove = function (e) { - invoke(mouseMoveCallback, [lastFound, e]); - pos.x = e.clientX; - pos.y = e.clientY; - }, - - handleMouseUp = function () { - documentEvents.stop('mousemove', handleMouseMove); - documentEvents.stop('mouseup', handleMouseUp); - }, - - updateBoundRect = function () { - boundRect = root.getBoundingClientRect(); - }; - - window.addEventListener('resize', updateBoundRect); - updateBoundRect(); - - // mouse move inside container serves only to track mouse enter/leave events. - root.addEventListener('mousemove', - function (e) { - if (mouseCapturedNode) { - return; - } - - var cancelBubble = false, - node; - - pos.x = e.clientX - boundRect.left; - pos.y = e.clientY - boundRect.top; - - node = getNodeAtClientPos(pos); - - if (node && lastFound !== node) { - lastFound = node; - cancelBubble = cancelBubble || invoke(mouseEnterCallback, [lastFound]); - } else if (node === null && lastFound !== node) { - cancelBubble = cancelBubble || invoke(mouseLeaveCallback, [lastFound]); - lastFound = null; - } - - if (cancelBubble) { stopPropagation(e); } - }); - - root.addEventListener('mousedown', - function (e) { - var cancelBubble = false, - args; - - pos.x = e.clientX - boundRect.left; - pos.y = e.clientY - boundRect.top; - - args = [getNodeAtClientPos(pos), e]; - if (args[0]) { - cancelBubble = invoke(mouseDownCallback, args); - // we clicked on a node. Following drag should be handled on document events: - documentEvents.on('mousemove', handleMouseMove); - documentEvents.on('mouseup', handleMouseUp); - - prevSelectStart = window.document.onselectstart; - - window.document.onselectstart = handleDisabledEvent; - - lastFound = args[0]; - } else { - lastFound = null; - } - if (cancelBubble) { stopPropagation(e); } - }); - - root.addEventListener('mouseup', - function (e) { - var clickTime = +new Date(), - args; - - pos.x = e.clientX - boundRect.left; - pos.y = e.clientY - boundRect.top; - - args = [getNodeAtClientPos(pos), e]; - if (args[0]) { - window.document.onselectstart = prevSelectStart; - - if (clickTime - lastClickTime < 400 && args[0] === lastFound) { - invoke(dblClickCallback, args); - } else { - invoke(clickCallback, args); - } - lastClickTime = clickTime; - - if (invoke(mouseUpCallback, args)) { - stopPropagation(e); - } - } - }); - }; - - // webgl may not be initialized at this point. Pass callback - // to start listen after graphics root is ready. - webglGraphics.getGraphicsRoot(startListen); - - webglGraphics.webglInputEvents = { - mouseEnter : function (callback) { - if (typeof callback === 'function') { - mouseEnterCallback.push(callback); - } - return this; - }, - mouseLeave : function (callback) { - if (typeof callback === 'function') { - mouseLeaveCallback.push(callback); - } - return this; - }, - mouseDown : function (callback) { - if (typeof callback === 'function') { - mouseDownCallback.push(callback); - } - return this; - }, - mouseUp : function (callback) { - if (typeof callback === 'function') { - mouseUpCallback.push(callback); - } - return this; - }, - mouseMove : function (callback) { - if (typeof callback === 'function') { - mouseMoveCallback.push(callback); - } - return this; - }, - click : function (callback) { - if (typeof callback === 'function') { - clickCallback.push(callback); - } - return this; - }, - dblClick : function (callback) { - if (typeof callback === 'function') { - dblClickCallback.push(callback); - } - return this; - }, - mouseCapture : function (node) { - mouseCapturedNode = node; - }, - releaseMouseCapture : function () { - mouseCapturedNode = null; - } - }; - - return webglGraphics.webglInputEvents; -}; -/** - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com - */ - -Viva.Input = Viva.Input || {}; -Viva.Input.webglInputManager = function (graph, graphics) { - var inputEvents = Viva.Graph.webglInputEvents(graphics), - draggedNode = null, - internalHandlers = {}, - pos = {x : 0, y : 0}; - - inputEvents.mouseDown(function (node, e) { - draggedNode = node; - pos.x = e.clientX; - pos.y = e.clientY; - - inputEvents.mouseCapture(draggedNode); - - var handlers = internalHandlers[node.id]; - if (handlers && handlers.onStart) { - handlers.onStart(e, pos); - } - - return true; - }).mouseUp(function (node) { - inputEvents.releaseMouseCapture(draggedNode); - - draggedNode = null; - var handlers = internalHandlers[node.id]; - if (handlers && handlers.onStop) { - handlers.onStop(); - } - return true; - }).mouseMove(function (node, e) { - if (draggedNode) { - var handlers = internalHandlers[draggedNode.id]; - if (handlers && handlers.onDrag) { - handlers.onDrag(e, {x : e.clientX - pos.x, y : e.clientY - pos.y }); - } - - pos.x = e.clientX; - pos.y = e.clientY; - return true; - } - }); - - return { - /** - * Called by renderer to listen to drag-n-drop events from node. E.g. for CSS/SVG - * graphics we may listen to DOM events, whereas for WebGL we graphics - * should provide custom eventing mechanism. - * - * @param node - to be monitored. - * @param handlers - object with set of three callbacks: - * onStart: function(), - * onDrag: function(e, offset), - * onStop: function() - */ - bindDragNDrop : function (node, handlers) { - internalHandlers[node.id] = handlers; - if (!handlers) { - delete internalHandlers[node.id]; - } - } - }; -}; +/** + * Monitors graph-related mouse input in webgl graphics and notifies subscribers. + * + * @param {Viva.Graph.View.webglGraphics} webglGraphics + */ +Viva.Graph.webglInputEvents = function (webglGraphics) { + if (webglGraphics.webglInputEvents) { + // Don't listen twice, if we are already attached to this graphics: + return webglGraphics.webglInputEvents; + } + + var preciseCheck = function (nodeUI, x, y) { + if (nodeUI && nodeUI.size) { + var pos = nodeUI.position, + half = nodeUI.size; + + return pos.x - half < x && x < pos.x + half && + pos.y - half < y && y < pos.y + half; + } + + return true; + }, + getNodeAtClientPos = function (pos) { + return webglGraphics.getNodeAtClientPos(pos, preciseCheck); + }, + mouseCapturedNode = null, + + mouseEnterCallback = [], + mouseLeaveCallback = [], + mouseDownCallback = [], + mouseUpCallback = [], + mouseMoveCallback = [], + clickCallback = [], + dblClickCallback = [], + documentEvents = Viva.Graph.Utils.events(window.document), + prevSelectStart, + boundRect, + + stopPropagation = function (e) { + if (e.stopPropagation) { + e.stopPropagation(); + } else { + e.cancelBubble = true; + } + }, + + handleDisabledEvent = function (e) { + stopPropagation(e); + return false; + }, + + invoke = function (callbacksChain, args) { + var i, stopPropagation; + for (i = 0; i < callbacksChain.length; i += 1) { + stopPropagation = callbacksChain[i].apply(undefined, args); + if (stopPropagation) { return true; } + } + }, + + startListen = function (root) { + var pos = {x : 0, y : 0}, + lastFound = null, + lastClickTime = +new Date(), + + handleMouseMove = function (e) { + invoke(mouseMoveCallback, [lastFound, e]); + pos.x = e.clientX; + pos.y = e.clientY; + }, + + handleMouseUp = function () { + documentEvents.stop('mousemove', handleMouseMove); + documentEvents.stop('mouseup', handleMouseUp); + }, + + updateBoundRect = function () { + boundRect = root.getBoundingClientRect(); + }; + + window.addEventListener('resize', updateBoundRect); + updateBoundRect(); + + // mouse move inside container serves only to track mouse enter/leave events. + root.addEventListener('mousemove', + function (e) { + if (mouseCapturedNode) { + return; + } + + var cancelBubble = false, + node; + + pos.x = e.clientX - boundRect.left; + pos.y = e.clientY - boundRect.top; + + node = getNodeAtClientPos(pos); + + if (node && lastFound !== node) { + lastFound = node; + cancelBubble = cancelBubble || invoke(mouseEnterCallback, [lastFound]); + } else if (node === null && lastFound !== node) { + cancelBubble = cancelBubble || invoke(mouseLeaveCallback, [lastFound]); + lastFound = null; + } + + if (cancelBubble) { stopPropagation(e); } + }); + + root.addEventListener('mousedown', + function (e) { + var cancelBubble = false, + args; + + pos.x = e.clientX - boundRect.left; + pos.y = e.clientY - boundRect.top; + + args = [getNodeAtClientPos(pos), e]; + if (args[0]) { + cancelBubble = invoke(mouseDownCallback, args); + // we clicked on a node. Following drag should be handled on document events: + documentEvents.on('mousemove', handleMouseMove); + documentEvents.on('mouseup', handleMouseUp); + + prevSelectStart = window.document.onselectstart; + + window.document.onselectstart = handleDisabledEvent; + + lastFound = args[0]; + } else { + lastFound = null; + } + if (cancelBubble) { stopPropagation(e); } + }); + + root.addEventListener('mouseup', + function (e) { + var clickTime = +new Date(), + args; + + pos.x = e.clientX - boundRect.left; + pos.y = e.clientY - boundRect.top; + + args = [getNodeAtClientPos(pos), e]; + if (args[0]) { + window.document.onselectstart = prevSelectStart; + + if (clickTime - lastClickTime < 400 && args[0] === lastFound) { + invoke(dblClickCallback, args); + } else { + invoke(clickCallback, args); + } + lastClickTime = clickTime; + + if (invoke(mouseUpCallback, args)) { + stopPropagation(e); + } + } + }); + }; + + // webgl may not be initialized at this point. Pass callback + // to start listen after graphics root is ready. + webglGraphics.getGraphicsRoot(startListen); + + webglGraphics.webglInputEvents = { + mouseEnter : function (callback) { + if (typeof callback === 'function') { + mouseEnterCallback.push(callback); + } + return this; + }, + mouseLeave : function (callback) { + if (typeof callback === 'function') { + mouseLeaveCallback.push(callback); + } + return this; + }, + mouseDown : function (callback) { + if (typeof callback === 'function') { + mouseDownCallback.push(callback); + } + return this; + }, + mouseUp : function (callback) { + if (typeof callback === 'function') { + mouseUpCallback.push(callback); + } + return this; + }, + mouseMove : function (callback) { + if (typeof callback === 'function') { + mouseMoveCallback.push(callback); + } + return this; + }, + click : function (callback) { + if (typeof callback === 'function') { + clickCallback.push(callback); + } + return this; + }, + dblClick : function (callback) { + if (typeof callback === 'function') { + dblClickCallback.push(callback); + } + return this; + }, + mouseCapture : function (node) { + mouseCapturedNode = node; + }, + releaseMouseCapture : function () { + mouseCapturedNode = null; + } + }; + + return webglGraphics.webglInputEvents; +}; +/** + * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + */ + +Viva.Input = Viva.Input || {}; +Viva.Input.webglInputManager = function (graph, graphics) { + var inputEvents = Viva.Graph.webglInputEvents(graphics), + draggedNode = null, + internalHandlers = {}, + pos = {x : 0, y : 0}; + + inputEvents.mouseDown(function (node, e) { + draggedNode = node; + pos.x = e.clientX; + pos.y = e.clientY; + + inputEvents.mouseCapture(draggedNode); + + var handlers = internalHandlers[node.id]; + if (handlers && handlers.onStart) { + handlers.onStart(e, pos); + } + + return true; + }).mouseUp(function (node) { + inputEvents.releaseMouseCapture(draggedNode); + + draggedNode = null; + var handlers = internalHandlers[node.id]; + if (handlers && handlers.onStop) { + handlers.onStop(); + } + return true; + }).mouseMove(function (node, e) { + if (draggedNode) { + var handlers = internalHandlers[draggedNode.id]; + if (handlers && handlers.onDrag) { + handlers.onDrag(e, {x : e.clientX - pos.x, y : e.clientY - pos.y }); + } + + pos.x = e.clientX; + pos.y = e.clientY; + return true; + } + }); + + return { + /** + * Called by renderer to listen to drag-n-drop events from node. E.g. for CSS/SVG + * graphics we may listen to DOM events, whereas for WebGL we graphics + * should provide custom eventing mechanism. + * + * @param node - to be monitored. + * @param handlers - object with set of three callbacks: + * onStart: function(), + * onDrag: function(e, offset), + * onStop: function() + */ + bindDragNDrop : function (node, handlers) { + internalHandlers[node.id] = handlers; + if (!handlers) { + delete internalHandlers[node.id]; + } + } + }; +}; diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index d398e6f..d2ea134 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.72",Viva.lazyExtend=function(a,b){var c;if(a||(a={}),b)for(c in b)if(b.hasOwnProperty(c)){var d=a.hasOwnProperty(c),e=typeof b[c],f=!d||typeof a[c]!==e;f?a[c]=b[c]:"object"===e&&(a[c]=Viva.lazyExtend(a[c],b[c]))}return a},Viva.random=function(){var a,b=arguments[0];a="number"==typeof b?b:"string"==typeof b?b.length:+new Date;var c=function(){return a=a+2127912214+(a<<12)&4294967295,a=4294967295&(3345072700^a^a>>>19),a=a+374761393+(a<<5)&4294967295,a=4294967295&(a+3550635116^a<<9),a=a+4251993797+(a<<3)&4294967295,a=4294967295&(3042594569^a^a>>>16),(268435455&a)/268435456};return{next:function(a){return Math.floor(c()*a)},nextDouble:function(){return c()}}},Viva.randomIterator=function(a,b){return b=b||Viva.random(),{forEach:function(c){var d,e,f;for(d=a.length-1;d>0;--d)e=b.next(d+1),f=a[e],a[e]=a[d],a[d]=f,c(f);a.length&&c(a[0])},shuffle:function(){var c,d,e;for(c=a.length-1;c>0;--c)d=b.next(c+1),e=a[d],a[d]=a[c],a[c]=e;return a}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var a=window.navigator.userAgent.toLowerCase(),b=/(webkit)[ \/]([\w.]+)/,c=/(opera)(?:.*version)?[ \/]([\w.]+)/,d=/(msie) ([\w.]+)/,e=/(mozilla)(?:.*? rv:([\w.]+))?/,f=b.exec(a)||c.exec(a)||d.exec(a)||a.indexOf("compatible")<0&&e.exec(a)||[];return{browser:f[1]||"",version:f[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(a,b){if(b.indexOf)return b.indexOf(a);var c,d=b.length;for(c=0;d>c;c+=1)if(b.hasOwnProperty(c)&&b[c]===a)return c;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(a){if(!a)throw{message:"Cannot get dimensions of undefined container"};var b=a.clientWidth,c=a.clientHeight;return{left:0,top:0,width:b,height:c}},Viva.Graph.Utils.findElementPosition=function(a){var b=0,c=0;if(a.offsetParent)do b+=a.offsetLeft,c+=a.offsetTop;while(null!==(a=a.offsetParent));return[b,c]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(a){var b=function(a){var b={};return a.fire=function(a,c){var d,e,f,g;if("string"!=typeof a)throw"Only strings can be used as even type";if(b.hasOwnProperty(a))for(d=b[a],g=0;gc?d=-1:c>o&&(d=1),e(a,d,{x:a.touches[0].clientX,y:a.touches[0].clientY}),o=c,r(a),s(a)}},B=function(a){n=!1,i.stop("touchmove",A),i.stop("touchend",B),i.stop("touchcancel",B),h=null,d&&d(a)},C=function(a,c){r(a),s(a),l=c.clientX,m=c.clientY,h=a.target||a.srcElement,b&&b(a,{x:l,y:m}),n||(n=!0,i.on("touchmove",A),i.on("touchend",B),i.on("touchcancel",B))},D=function(b){return console.log("Touch start for ",a),1===b.touches.length?C(b,b.touches[0]):void(2===b.touches.length&&(r(b),s(b),o=z(b.touches[0],b.touches[1])))};return j.on("mousedown",v),j.on("touchstart",D),{onStart:function(a){return b=a,this},onDrag:function(a){return c=a,this},onStop:function(a){return d=a,this},onScroll:function(a){return y(a),this},release:function(){i.stop("mousemove",u),i.stop("mousedown",v),i.stop("mouseup",w),i.stop("touchmove",A),i.stop("touchend",B),i.stop("touchcancel",B),y(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(a,b){var c={};return{bindDragNDrop:function(a,d){var e;if(d){var f=b.getNodeUI(a.id);e=Viva.Graph.Utils.dragndrop(f),"function"==typeof d.onStart&&e.onStart(d.onStart),"function"==typeof d.onDrag&&e.onDrag(d.onDrag),"function"==typeof d.onStop&&e.onStop(d.onStop),c[a.id]=e}else(e=c[a.id])&&(e.release(),delete c[a.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var a,b,c=0,d=["ms","moz","webkit","o"];for(b="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},a=0;a=0==r>=4?null:(j=h-f,l=e-g,n=g*f-e*h,o=j*a+l*b+n,p=j*c+l*d+n,0!==o&&0!==p&&o>=0==p>=0?null:(s=i*l-j*k,0===s?null:(t=0>s?-s/2:s/2,t=0,u=k*n-l*m,v.x=(0>u?u-t:u+t)/s,u=j*m-i*n,v.y=(0>u?u-t:u+t)/s,v)))},intersectRect:function(a,b,c,d,e,f,g,h){return this.intersect(a,b,a,d,e,f,g,h)||this.intersect(a,d,c,d,e,f,g,h)||this.intersect(c,d,c,b,e,f,g,h)||this.intersect(c,b,a,b,e,f,g,h)},convexHull:function(a){var b=function(a,b){var c,d,e=function(b){var c=b.x-a.x,d=b.y-a.y,e=c>0?1:-1;return e*c*c/(c*c+d*d)},f=b.sort(function(a,b){return e(b)-e(a)}),g=f[0],h=e(g),i=g.x-a.x,j=g.y-a.y,k=i*i+j*j;for(d=1;dc?f.splice(d,1):f.splice(d-1,1)):h=l}return f},c=function(a,b,c){return(c.x-a.x)*(b.y-a.y)-(c.y-a.y)*(b.x-a.x)<0};if(a.length<3)return a;var d,e=0;for(d=0;d0&&(g(a),f.length=0)},j=function(a,b){f.push({node:a,changeType:b})},k=function(a,b){f.push({link:a,changeType:b})},l={addNode:function(b,c){if("undefined"==typeof b)throw{message:"Invalid node identifier"};h();var e=this.getNode(b);return e?j(e,"update"):(e=new Viva.Graph.Node(b),d++,j(e,"add")),e.data=c,a[b]=e,i(this),e},addLink:function(a,d,e){h();var f=this.getNode(a)||this.addNode(a),g=this.getNode(d)||this.addNode(d),j=a.toString()+"👉 "+d.toString(),l=c.hasOwnProperty(j);(l||this.hasLink(a,d))&&(l||(c[j]=0),j+="@"+ ++c[j]);var m=new Viva.Graph.Link(a,d,e,j);return b.push(m),f.links.push(m),g.links.push(m),k(m,"add"),i(this),m},removeLink:function(a){if(!a)return!1;var c=Viva.Graph.Utils.indexOfElementInArray(a,b);if(0>c)return!1;h(),b.splice(c,1);var d=this.getNode(a.fromId),e=this.getNode(a.toId);return d&&(c=Viva.Graph.Utils.indexOfElementInArray(a,d.links),c>=0&&d.links.splice(c,1)),e&&(c=Viva.Graph.Utils.indexOfElementInArray(a,e.links),c>=0&&e.links.splice(c,1)),k(a,"remove"),i(this),!0},removeNode:function(b){var c=this.getNode(b);if(!c)return!1;for(h();c.links.length;){var e=c.links[0];this.removeLink(e)}a[b]=null,delete a[b],d--,j(c,"remove"),i(this)},getNode:function(b){return a[b]},getNodesCount:function(){return d},getLinksCount:function(){return b.length},getLinks:function(a){var b=this.getNode(a);return b?b.links:null},forEachNode:function(b){if("function"==typeof b){var c;for(c in a)if(b(a[c]))return}},forEachLinkedNode:function(b,c,d){var e,f,g,h=this.getNode(b);if(h&&h.links&&"function"==typeof c)if(d)for(e=0;ec;++c)a(b[c])},beginUpdate:function(){h()},endUpdate:function(){i(this)},clear:function(){var a=this;a.beginUpdate(),a.forEachNode(function(b){a.removeNode(b.id)}),a.endUpdate()},hasLink:function(a,b){var c,d=this.getNode(a);if(!d)return null;for(c=0;cc;++c){var j=a.bodies[c],k=b/j.mass;j.velocity.x+=k*j.force.x,j.velocity.y+=k*j.force.y;var l=j.velocity.x,m=j.velocity.y,n=Math.sqrt(l*l+m*m);n>d&&(j.velocity.x=d*l/n,j.velocity.y=d*m/n),f=b*j.velocity.x,h=b*j.velocity.y,j.location.x+=f,j.location.y+=h,e+=f,g+=h}return(e*e+g*g)/i}}},Viva.Graph.Physics.nbodyForce=function(a){function b(a,b){this.node=a,this.body=b}function c(){this.stack=[],this.popIdx=0}a=Viva.lazyExtend(a||{gravity:-1,theta:.8}),c.prototype={isEmpty:function(){return 0===this.popIdx},push:function(a,c){var d=this.stack[this.popIdx];d?(d.node=a,d.body=c):this.stack[this.popIdx]=new b(a,c),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var d=a.gravity,e=[],f=new c,g=a.theta,h=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),i=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},j=[],k=0,l=function(){var a;return j[k]?(a=j[k],a.quads[0]=null,a.quads[1]=null,a.quads[2]=null,a.quads[3]=null,a.body=null,a.mass=a.massX=a.massY=0,a.left=a.right=a.top=a.bottom=0,a.isInternal=!1):(a=new i,j[k]=a),++k,a},m=l(),n=function(a,b){var c=Math.abs(a.x-b.x),d=Math.abs(a.y-b.y);return 1e-8>c&&1e-8>d},o=function(a){for(f.reset(),f.push(m,a);!f.isEmpty();){var b=f.pop(),c=b.node,d=b.body;if(c.isInternal){var e=d.location.x,g=d.location.y;c.mass=c.mass+d.mass,c.massX=c.massX+d.mass*e,c.massY=c.massY+d.mass*g;var i=0,j=c.left,k=(c.right+j)/2,o=c.top,p=(c.bottom+o)/2;if(e>k){i+=1;var q=j;j=k,k+=k-q}if(g>p){i+=2;var r=o;o=p,p+=p-r}var s=c.quads[i];s||(s=l(),s.left=j,s.top=o,s.right=k,s.bottom=p,c.quads[i]=s),f.push(s,d)}else if(c.body){var t=c.body;if(c.body=null,c.isInternal=!0,n(t.location,d.location)){if(c.right-c.left<1e-8)return;do{var u=h.nextDouble(),v=(c.right-c.left)*u,w=(c.bottom-c.top)*u;t.location.x=c.left+v,t.location.y=c.top+w}while(n(t.location,d.location))}f.push(c,t),f.push(c,d)}else c.body=d}},p=function(a){var b,c,f,i,j=e,k=1,l=0,n=1;for(j[0]=m;k;){var o=j[l],p=o.body;k-=1,l+=1,p&&p!==a?(c=p.location.x-a.location.x,f=p.location.y-a.location.y,i=Math.sqrt(c*c+f*f),0===i&&(c=(h.nextDouble()-.5)/50,f=(h.nextDouble()-.5)/50,i=Math.sqrt(c*c+f*f)),b=d*p.mass*a.mass/(i*i*i),a.force.x=a.force.x+b*c,a.force.y=a.force.y+b*f):(c=o.massX/o.mass-a.location.x,f=o.massY/o.mass-a.location.y,i=Math.sqrt(c*c+f*f),0===i&&(c=(h.nextDouble()-.5)/50,f=(h.nextDouble()-.5)/50,i=Math.sqrt(c*c+f*f)),(o.right-o.left)/ii&&(c=i),i>e&&(e=i),d>j&&(d=j),j>f&&(f=j)}var n=e-c,p=f-d;for(n>p?f=d+n:e=c+p,k=0,m=l(),m.left=c,m.right=e,m.top=d,m.bottom=f,b=h;b--;)o(g[b],m)};return{insert:o,init:q,update:p,options:function(a){return a?("number"==typeof a.gravity&&(d=a.gravity),"number"==typeof a.theta&&(g=a.theta),this):{gravity:d,theta:g}}}},Viva.Graph.Physics.dragForce=function(a){a||(a={});var b={coeff:a.coeff||.01};return{update:function(a){a.force.x-=b.coeff*a.velocity.x,a.force.y-=b.coeff*a.velocity.y},options:function(a){return a?("number"==typeof a.coeff&&(b.coeff=a.coeff),this):b}}},Viva.Graph.Physics.springForce=function(a){a=Viva.lazyExtend(a,{length:50,coeff:22e-5});var b=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(c){var d=c.body1,e=c.body2,f=c.length<0?a.length:c.length,g=e.location.x-d.location.x,h=e.location.y-d.location.y,i=Math.sqrt(g*g+h*h);0===i&&(g=(b.nextDouble()-.5)/50,h=(b.nextDouble()-.5)/50,i=Math.sqrt(g*g+h*h));var j=i-f,k=(!c.coeff||c.coeff<0?a.coeff:c.coeff)*j/i*c.weight;d.force.x+=k*g,d.force.y+=k*h,e.force.x+=-k*g,e.force.y+=-k*h},options:function(b){return b?("number"==typeof b.length&&(a.length=b.length),"number"==typeof b.coeff&&(a.coeff=b.coeff),this):a}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(a){var b,c,d,e=a,f=[],g=[];return{speedLimit:1,bodies:f,accumulate:function(){var a,e;for(c.init(this),a=f.length;a--;)e=f[a],e.force.x=0,e.force.y=0,c.update(e),d.update(e);for(a=g.length;a--;)b.update(g[a])},run:function(a){return this.accumulate(),e.integrate(this,a)},addBody:function(a){if(!a)throw{message:"Cannot add null body to force simulator"};return f.push(a),a},removeBody:function(a){if(!a)return!1;var b=Viva.Graph.Utils.indexOfElementInArray(a,f);return 0>b?!1:f.splice(b,1)},addSpring:function(a,b,c,d,e){if(!a||!b)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof c)throw{message:"Spring length should be a number"};d="number"==typeof d?d:1;var f=new Viva.Graph.Physics.Spring(a,b,c,e>=0?e:-1,d);return g.push(f),f},removeSpring:function(a){if(!a)return!1;var b=Viva.Graph.Utils.indexOfElementInArray(a,g);return 0>b?!1:g.splice(b,1)},setNbodyForce:function(a){if(!a)throw{message:"Cannot add mighty (unknown) force to the simulator"};c=a},setDragForce:function(a){if(!a)throw{message:"Cannot add mighty (unknown) force to the simulator"};d=a},setSpringForce:function(a){if(!a)throw{message:"Cannot add unknown force to the simulator"};b=a}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(a,b){if(!a)throw{message:"Graph structure cannot be undefined"};b=Viva.lazyExtend(b,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02,springTransform:function(){},timeStep:20,stableThreshold:.001});var c=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),d=Viva.Graph.Physics.nbodyForce({gravity:b.gravity,theta:b.theta}),e=Viva.Graph.Physics.springForce({length:b.springLength,coeff:b.springCoeff}),f=Viva.Graph.Physics.dragForce({coeff:b.dragCoeff}),g=new Viva.Graph.Rect,h=Viva.random("ted.com",103,114,101,97,116),i={},j=function(a){if(a.position)return a.position;var c=(g.x1+g.x2)/2,d=(g.y1+g.y2)/2,e=b.springLength;if(a.links&&a.links.length>0){var f=a.links[0],j=f.fromId!==a.id?i[f.fromId]:i[f.toId];j&&j.location&&(c=j.location.x,d=j.location.y)}return{x:c+h.next(e)-e/2,y:d+h.next(e)-e/2}},k=function(a){return i[a]},l=function(a){i[a]=null,delete i[a]},m={},n=function(b){var c=k(b);c.mass=1+a.getLinks(b).length/3},o=function(a){return a&&(a.isPinned||a.data&&a.data.isPinned)},p=function(a){return a.isPinned},q=function(b){var d=k(b);if(!d){var e=a.getNode(b);if(!e)return;d=new Viva.Graph.Physics.Body,i[b]=d;var f=j(e);d.loc(f),n(b),o(e)&&(d.isPinned=!0),c.addBody(d)}},r=function(a){q(a.id)},s=function(b){var d=k(b.id);d&&(l(b.id),c.removeBody(d),0===a.getNodesCount()&&(g.x1=g.y1=0,g.x2=g.y2=0))},t=function(a){n(a.fromId),n(a.toId);var d=k(a.fromId),e=k(a.toId),f=c.addSpring(d,e,-1,a.weight);b.springTransform(a,f),m[a.id]=f},u=function(b){var d=m[b.id];if(d){var e=a.getNode(b.fromId),f=a.getNode(b.toId);e&&n(e.id),f&&n(f.id),delete m[b.id],c.removeSpring(d)}},v=function(a){for(var b=0;bd&&(d=h.location.x),h.location.ye&&(e=h.location.y)}g.x1=b,g.x2=d,g.y1=c,g.y2=e}};return c.setSpringForce(e),c.setNbodyForce(d),c.setDragForce(f),w(),{run:function(a){var b;for(a=a||50,b=0;a>b;++b)this.step()},step:function(){var a=c.run(b.timeStep);return x(),ab.x2&&(b.x2=a.x),a.yb.y2&&(b.y2=a.y)},g="function"==typeof Object.create?Object.create(null):{},h=function(a){a&&(g[a.id]=e(a),f(g[a.id],d))},i=function(){0!==a.getNodesCount()&&(d.x1=Number.MAX_VALUE,d.y1=Number.MAX_VALUE,d.x2=Number.MIN_VALUE,d.y2=Number.MIN_VALUE,a.forEachNode(h))},j=function(a){for(var b=0;b0)for(a=0;ab,c)}),a.forEachNode(H),Q(),f=Viva.Graph.Utils.events(a),f.on("changed",N)},T=function(){l=!1,Q(),P(),v.stop("resize",O),w.removeAllListeners(),e.stop(),a.forEachLink(function(a){b.renderLinks&&G(a)}),a.forEachNode(function(a){I(a),E(a)}),h.dispose(),K()};return{run:function(a){return l||(u(),B(),C(),J(),S(),l=!0),z(a),this},reset:function(){i.resetScale(),C(),t.scale=1},pause:function(){r=!0,e.stop()},resume:function(){r=!1,e.restart()},rerender:function(){return x(),this},zoomOut:function(){return R(!0)},zoomIn:function(){return R(!1)},moveTo:function(a,b){i.graphCenterChanged(t.offsetX-a*t.scale,t.offsetY-b*t.scale),x()},getGraphics:function(){return i},dispose:function(){T()},on:function(a,b){return w.addEventListener(a,b),this},off:function(a,b){return w.removeEventListener(a,b),this}}},Viva.Graph.serializer=function(){var a=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},b=function(a){return{id:a.id,data:a.data}},c=function(a){return{fromId:a.fromId,toId:a.toId,data:a.data}},d=function(a){return a},e=function(a){return a};return{storeToJSON:function(d,e,f){if(!d)throw"Graph is not defined";a(),e=e||b,f=f||c;var g={nodes:[],links:[]};return d.forEachNode(function(a){g.nodes.push(e(a))}),d.forEachLink(function(a){g.links.push(f(a))}),JSON.stringify(g)},loadFromJSON:function(b,c,f){if("string"!=typeof b)throw"String expected in loadFromJSON() method";a(),c=c||d,f=f||e;var g,h=JSON.parse(b),i=Viva.Graph.graph();if(!h||!h.nodes||!h.links)throw"Passed json string does not represent valid graph";for(g=0;gc?void d.push({name:a,probability:e/b}):!0}),d},g=function(a){var b=[];return a.forEachNode(function(a){var c=Viva.Graph._community.occuranceMap(d);c.add(a.id),a.slpa={memory:c},b.push(a.id)}),b},h=function(a,c){var f,g=Viva.randomIterator(c,e),h=function(b){var c=a.getNode(b),e=Viva.Graph._community.occuranceMap(d);a.forEachLinkedNode(b,function(a){var b=a.slpa.memory.getRandomWord();e.add(b)});var f=e.getMostPopularFair();c.slpa.memory.add(f)};for(f=0;b-1>f;++f)g.forEach(h)},i=function(a){var d={};return a.forEachNode(function(a){var e,g=f(a.slpa.memory,c*b);for(e=0;ea?-1:a>c?1:0})},g=function(){d&&(f(),d=!1)};return{add:function(a){a=String(a),b.hasOwnProperty(a)?b[a]+=1:b[a]=1,c.push(a),d=!0},getWordCount:function(a){return b[a]||0},getMostPopularFair:function(){if(1===c.length)return c[0];g();var d,f=0;for(d=1;da)throw{message:"At least two nodes expected for complete graph"};var b,c,d=Viva.Graph.graph();for(d.Name="Complete K"+a,b=0;a>b;++b)for(c=b+1;a>c;++c)b!==c&&d.addLink(b,c);return d},completeBipartite:function(a,b){if(!a||!b||0>a||0>b)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var c,d,e=Viva.Graph.graph();for(e.Name="Complete K "+a+","+b,c=0;a>c;++c)for(d=a;a+b>d;++d)e.addLink(c,d); -return e},ladder:function(a){if(!a||0>a)throw{message:"Invalid number of nodes"};var b,c=Viva.Graph.graph();for(c.Name="Ladder graph "+a,b=0;a-1>b;++b)c.addLink(b,b+1),c.addLink(a+b,a+b+1),c.addLink(b,a+b);return c.addLink(a-1,2*a-1),c},circularLadder:function(a){if(!a||0>a)throw{message:"Invalid number of nodes"};var b=this.ladder(a);return b.Name="Circular ladder graph "+a,b.addLink(0,a-1),b.addLink(a,2*a-1),b},grid:function(a,b){var c,d,e=Viva.Graph.graph();for(e.Name="Grid graph "+a+"x"+b,c=0;a>c;++c)for(d=0;b>d;++d){var f=c+d*a;c>0&&e.addLink(f,c-1+d*a),d>0&&e.addLink(f,c+(d-1)*a)}return e},path:function(a){if(!a||0>a)throw{message:"Invalid number of nodes"};var b,c=Viva.Graph.graph();for(c.Name="Path graph "+a,c.addNode(0),b=1;a>b;++b)c.addLink(b-1,b);return c},lollipop:function(a,b){if(!b||0>b||!a||0>a)throw{message:"Invalid number of nodes"};var c,d=this.complete(a);for(d.Name="Lollipop graph. Head x Path "+a+"x"+b,c=0;b>c;++c)d.addLink(a+c-1,a+c);return d},balancedBinTree:function(a){var b,c=Viva.Graph.graph(),d=Math.pow(2,a);for(c.Name="Balanced bin tree graph "+a,b=1;d>b;++b){var e=b,f=2*e,g=2*e+1;c.addLink(e,f),c.addLink(e,g)}return c},randomNoLinks:function(a){if(!a||0>a)throw{message:"Invalid number of nodes"};var b,c=Viva.Graph.graph();for(c.Name="Random graph, no Links: "+a,b=0;a>b;++b)c.addNode(b);return c}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var a,b,c,d="OLD_IE",e=1,f=1,g=function(){var a,b,c=Viva.BrowserInfo.browser;switch(c){case"mozilla":a="Moz";break;case"webkit":a="webkit";break;case"opera":a="O";break;case"msie":if(b=Viva.BrowserInfo.version.split(".")[0],!(b>8))return d;a="ms"}return a?a+"Transform":null}(),h=function(){return g===d?function(a,b,c,d){var e=Math.cos(d),f=Math.sin(d);0>d&&(d=2*Math.PI+d),d=n.byteLength){var a=new ArrayBuffer(2*n.byteLength),b=new Float32Array(a),c=new Uint32Array(a);c.set(p),o=b,p=c,n=a}};return{load:function(f){b=f,e=Viva.Graph.webgl(f),a=e.createProgram(m,l),b.useProgram(a),d=e.getLocations(a,["a_vertexPos","a_color","u_screenSize","u_transform"]),b.enableVertexAttribArray(d.vertexPos),b.enableVertexAttribArray(d.color),c=b.createBuffer()},position:function(a,b){var c=a.id;o[c*j]=b.x,o[c*j+1]=b.y,o[c*j+2]=a.size,p[c*j+3]=a.color},updateTransform:function(a){i=!0,h=a},updateSize:function(a,b){f=a,g=b,i=!0},removeNode:function(a){q>0&&(q-=1),a.id0&&e.copyArrayPart(p,a.id*j,q*j,j)},createNode:function(){r(),q+=1},replaceProperties:function(){},render:function(){b.useProgram(a),b.bindBuffer(b.ARRAY_BUFFER,c),b.bufferData(b.ARRAY_BUFFER,n,b.DYNAMIC_DRAW),i&&(i=!1,b.uniformMatrix4fv(d.transform,!1,h),b.uniform2f(d.screenSize,f,g)),b.vertexAttribPointer(d.vertexPos,3,b.FLOAT,!1,j*Float32Array.BYTES_PER_ELEMENT,0),b.vertexAttribPointer(d.color,4,b.UNSIGNED_BYTE,!0,j*Float32Array.BYTES_PER_ELEMENT,12),b.drawArrays(b.POINTS,0,q)}}},Viva.Graph.View.webglLinkProgram=function(){var a,b,c,d,e,f,g,h,i,j,k=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),m=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),n=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),o=0,p=new ArrayBuffer(16*l),q=new Float32Array(p),r=new Uint32Array(p),s=function(){if((o+1)*l>p.byteLength){var a=new ArrayBuffer(2*p.byteLength),b=new Float32Array(a),c=new Uint32Array(a);c.set(r),q=b,r=c,p=a}};return{load:function(f){b=f,d=Viva.Graph.webgl(f),a=d.createProgram(n,m),b.useProgram(a),e=d.getLocations(a,["a_vertexPos","a_color","u_screenSize","u_transform"]),b.enableVertexAttribArray(e.vertexPos),b.enableVertexAttribArray(e.color),c=b.createBuffer()},position:function(a,b,c){var d=a.id,e=d*k;q[e]=b.x,q[e+1]=b.y,r[e+2]=a.color,q[e+3]=c.x,q[e+4]=c.y,r[e+5]=a.color},createLink:function(a){s(),o+=1,f=a.id},removeLink:function(a){o>0&&(o-=1),a.id0&&d.copyArrayPart(r,a.id*k,o*k,k)},updateTransform:function(a){j=!0,i=a},updateSize:function(a,b){g=a,h=b,j=!0},render:function(){b.useProgram(a),b.bindBuffer(b.ARRAY_BUFFER,c),b.bufferData(b.ARRAY_BUFFER,p,b.DYNAMIC_DRAW),j&&(j=!1,b.uniformMatrix4fv(e.transform,!1,i),b.uniform2f(e.screenSize,g,h)),b.vertexAttribPointer(e.vertexPos,2,b.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),b.vertexAttribPointer(e.color,4,b.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),b.drawArrays(b.LINES,0,2*o),f=o-1},bringToFront:function(a){f>a.id&&d.swapArrayPart(q,a.id*k,f*k,k),f>0&&(f-=1)},getFrontLinkId:function(){return f}}},Viva.Graph.View.Texture=function(a){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=a},Viva.Graph.View.webglAtlas=function(a){var b,c,d=Math.sqrt(a||1024)<<0,e=d,f=1,g={},h=0,i=[],j=[],k=function(a){return 0===(a&a-1)},l=function(){var a=new Viva.Graph.View.Texture(d*e);i.push(a)},m=function(b){var c=b/a<<0,e=b%a,f=e/d<<0,g=e%d;return{textureNumber:c,row:f,col:g}},n=function(){c.isDirty=!0,h=0,b=null},o=function(){b&&(window.clearTimeout(b),h+=1,b=null),h>10?n():b=window.setTimeout(n,400)},p=function(a,b){var c=i[a.textureNumber].canvas,d=i[b.textureNumber].ctx,f=b.col*e,g=b.row*e;d.drawImage(c,a.col*e,a.row*e,e,e,f,g,e,e),i[a.textureNumber].isDirty=!0,i[b.textureNumber].isDirty=!0},q=function(a,b,c){var d=m(a),f={offset:a};d.textureNumber>=i.length&&l();var h=i[d.textureNumber];h.ctx.drawImage(b,d.col*e,d.row*e,e,e),j[a]=b.src,g[b.src]=f,h.isDirty=!0,c(f)};if(!k(a))throw"Tiles per texture should be power of two.";return c={isDirty:!1,clearDirty:function(){var a;for(this.isDirty=!1,a=0;a0&&(o-=1),b.id0&&(b.src&&a.remove(b.src),e.copyArrayPart(p,b.id*k,o*k,k))},replaceProperties:function(a,b){b._offset=a._offset},updateTransform:function(a){j=!0,i=a},updateSize:function(a,b){g=a,h=b,j=!0},render:function(){c.useProgram(b),c.bindBuffer(c.ARRAY_BUFFER,d),c.bufferData(c.ARRAY_BUFFER,p,c.DYNAMIC_DRAW),j&&(j=!1,c.uniformMatrix4fv(f.transform,!1,i),c.uniform2f(f.screenSize,g,h)),c.vertexAttribPointer(f.vertexPos,2,c.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),c.vertexAttribPointer(f.customAttributes,1,c.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),r(),c.drawArrays(c.TRIANGLES,0,6*o)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(a){a=Viva.lazyExtend(a,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var b,c,d,e,f,g,h,i,j=0,k=0,l=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],m=[],n=[],o={},p={},q=Viva.Graph.View.webglLinkProgram(),r=Viva.Graph.View.webglNodeProgram(),s=function(){return Viva.Graph.View.webglSquare()},t=function(){return Viva.Graph.View.webglLine(3014898687)},u=function(){q.updateTransform(l),r.updateTransform(l)},v=function(){l=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},w=function(){b&&c&&(e=c.width=Math.max(b.offsetWidth,1),f=c.height=Math.max(b.offsetHeight,1),d&&d.viewport(0,0,e,f),q&&q.updateSize(e/2,f/2),r&&r.updateSize(e/2,f/2))},x=function(a){a.fire("rescaled")},y={getLinkUI:function(a){return p[a]},getNodeUI:function(a){return o[a]},node:function(a){return"function"==typeof a?(s=a,this):void 0},link:function(a){return"function"==typeof a?(t=a,this):void 0},placeNode:function(a){return g=a,this},placeLink:function(a){return h=a,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){k>0&&q.render(),j>0&&r.render()},bringLinkToFront:function(a){var b,c,d=q.getFrontLinkId();q.bringToFront(a),d>a.id&&(b=a.id,c=n[d],n[d]=n[b],n[d].id=d,n[b]=c,n[b].id=b)},graphCenterChanged:function(a,b){l[12]=2*a/e-1,l[13]=1-2*b/f,u()},addLink:function(a,b){var c=k++,d=t(a);return d.id=c,d.pos=b,q.createLink(d),n[c]=d,p[a.id]=d,d},addNode:function(a,b){var c=j++,d=s(a);return d.id=c,d.position=b,d.node=a,r.createNode(d),m[c]=d,o[a.id]=d,d},translateRel:function(a,b){l[12]+=2*l[0]*a/e/l[0],l[13]-=2*l[5]*b/f/l[5],u()},scale:function(a,b){var c=2*b.x/e-1,d=1-2*b.y/f;return c-=l[12],d-=l[13],l[12]+=c*(1-a),l[13]+=d*(1-a),l[0]*=a,l[5]*=a,u(),x(this),l[0]},resetScale:function(){return v(),d&&(w(),u()),this},init:function(g){var h={};if(a.preserveDrawingBuffer&&(h.preserveDrawingBuffer=!0),b=g,c=window.document.createElement("canvas"),w(),v(),b.appendChild(c),d=c.getContext("experimental-webgl",h),!d){var j="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(j),j}if(a.enableBlending&&(d.blendFunc(d.SRC_ALPHA,d.ONE_MINUS_SRC_ALPHA),d.enable(d.BLEND)),a.clearColor){var k=a.clearColorValue;d.clearColor(k.r,k.g,k.b,k.a),this.beginRender=function(){d.clear(d.COLOR_BUFFER_BIT)}}q.load(d),q.updateSize(e/2,f/2),r.load(d),r.updateSize(e/2,f/2),u(),"function"==typeof i&&i(c)},release:function(a){c&&a&&a.removeChild(c)},isSupported:function(){var a=window.document.createElement("canvas"),b=a&&a.getContext&&a.getContext("experimental-webgl");return b},releaseLink:function(a){k>0&&(k-=1);var b=p[a.id];delete p[a.id],q.removeLink(b);var c=b.id;if(k>c){if(0===k||k===c)return;var d=n[k];n[c]=d,d.id=c}},releaseNode:function(a){j>0&&(j-=1);var b=o[a.id];delete o[a.id],r.removeNode(b);var c=b.id;if(j>c){if(0===j||j===c)return;var d=m[j];m[c]=d,d.id=c,r.replaceProperties(b,d)}},renderNodes:function(){for(var a={x:0,y:0},b=0;j>b;++b){var c=m[b];a.x=c.position.x,a.y=-c.position.y,g&&g(c,a),r.position(c,a)}},renderLinks:function(){if(!this.omitLinksRendering)for(var a={x:0,y:0},b={x:0,y:0},c=0;k>c;++c){var d=n[c],e=d.pos.from;b.x=e.x,b.y=-e.y,e=d.pos.to,a.x=e.x,a.y=-e.y,h&&h(d,b,a),q.position(d,b,a)}},getGraphicsRoot:function(a){return"function"==typeof a&&(c?a(c):i=a),c},setNodeProgram:function(a){if(!d&&a)r=a;else if(a)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(a){if(!d&&a)q=a;else if(a)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(a){return a.x=2*a.x/e-1,a.y=1-2*a.y/f,a.x=(a.x-l[12])/l[0],a.y=(a.y-l[13])/l[5],a.x*=e/2,a.y*=-f/2,a},getNodeAtClientPos:function(a,b){if("function"!=typeof b)return null;this.transformClientToGraphCoordinates(a);for(var c=0;j>c;++c)if(b(m[c],a.x,a.y))return m[c].node;return null}};return Viva.Graph.Utils.events(y).extend(),y},Viva.Graph.webglInputEvents=function(a){if(a.webglInputEvents)return a.webglInputEvents;var b,c,d=function(a,b,c){if(a&&a.size){var d=a.position,e=a.size;return d.x-eg-s&&f[0]===r?q(m,f):q(l,f),s=g,q(j,f)&&o(a))})};return a.getGraphicsRoot(r),a.webglInputEvents={mouseEnter:function(a){return"function"==typeof a&&g.push(a),this},mouseLeave:function(a){return"function"==typeof a&&h.push(a),this},mouseDown:function(a){return"function"==typeof a&&i.push(a),this},mouseUp:function(a){return"function"==typeof a&&j.push(a),this},mouseMove:function(a){return"function"==typeof a&&k.push(a),this},click:function(a){return"function"==typeof a&&l.push(a),this},dblClick:function(a){return"function"==typeof a&&m.push(a),this},mouseCapture:function(a){f=a},releaseMouseCapture:function(){f=null}},a.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(a,b){var c=Viva.Graph.webglInputEvents(b),d=null,e={},f={x:0,y:0};return c.mouseDown(function(a,b){d=a,f.x=b.clientX,f.y=b.clientY,c.mouseCapture(d);var g=e[a.id];return g&&g.onStart&&g.onStart(b,f),!0}).mouseUp(function(a){c.releaseMouseCapture(d),d=null;var b=e[a.id];return b&&b.onStop&&b.onStop(),!0}).mouseMove(function(a,b){if(d){var c=e[d.id];return c&&c.onDrag&&c.onDrag(b,{x:b.clientX-f.x,y:b.clientY-f.y}),f.x=b.clientX,f.y=b.clientY,!0}}),{bindDragNDrop:function(a,b){e[a.id]=b,b||delete e[a.id]}}}; \ No newline at end of file +var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.8",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},N=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},P=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",N,!1):e.addEventListener("DOMMouseScroll",N,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",N,!1):e.removeEventListener("DOMMouseScroll",N,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return P(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),P(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e="function"==typeof Object.create?Object.create(null):{},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e,t){var n=e.getNodesCount();return 0===n?0/0:t?e.getLinksCount()/(n*(n-1)):2*e.getLinksCount()/(n*(n-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=0,u=0,s=e.bodies.length;for(n=0;s>n;++n){var f=e.bodies[n],c=t/f.mass;f.velocity.x+=c*f.force.x,f.velocity.y+=c*f.force.y;var d=f.velocity.x,l=f.velocity.y,h=Math.sqrt(d*d+l*l);h>r&&(f.velocity.x=r*d/h,f.velocity.y=r*l/h),o=t*f.velocity.x,u=t*f.velocity.y,f.location.x+=o,f.location.y+=u,i+=Math.abs(o),a+=Math.abs(u)}return(i+a)/s}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};r="number"==typeof r?r:1;var o=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,r);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02,springTransform:function(){},timeStep:20,stableThreshold:.009});var n=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),r=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),i=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),o=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),a=new Viva.Graph.Rect,u=Viva.random("ted.com",103,114,101,97,116),s={},f=function(e){if(e.position)return e.position;var n=(a.x1+a.x2)/2,r=(a.y1+a.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],f=o.fromId!==e.id?s[o.fromId]:s[o.toId];f&&f.location&&(n=f.location.x,r=f.location.y)}return{x:n+u.next(i)-i/2,y:r+u.next(i)-i/2}},c=function(e){return s[e]},d=function(e){s[e]=null,delete s[e]},l={},h=function(t){var n=c(t);n.mass=1+e.getLinks(t).length/3},v=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},p=function(e){return e.isPinned},m=function(t){var r=c(t);if(!r){var i=e.getNode(t);if(!i)return;r=new Viva.Graph.Physics.Body,s[t]=r;var o=f(i);r.loc(o),h(t),v(i)&&(r.isPinned=!0),n.addBody(r)}},g=function(e){m(e.id)},y=function(t){var r=c(t.id);r&&(d(t.id),n.removeBody(r),0===e.getNodesCount()&&(a.x1=a.y1=0,a.x2=a.y2=0))},x=function(e){h(e.fromId),h(e.toId);var r=c(e.fromId),i=c(e.toId),o=n.addSpring(r,i,-1,e.weight);t.springTransform(e,o),l[e.id]=o},w=function(t){var r=l[t.id];if(r){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&h(i.id),o&&h(o.id),delete l[t.id],n.removeSpring(r)}},V=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&m(n.node.id),n.link&&x(n.link)):"remove"===n.changeType&&(n.node&&y(n.node),n.link&&w(n.link))}},b=function(){e.forEachNode(g),e.forEachLink(x),e.addEventListener("changed",V)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in s)if(s.hasOwnProperty(o)){var u=s[o];p(u)?(u.location.x=u.prevLocation.x,u.location.y=u.prevLocation.y):(u.prevLocation.x=u.location.x,u.prevLocation.y=u.location.y),t>u.location.x&&(t=u.location.x),u.location.x>r&&(r=u.location.x),n>u.location.y&&(n=u.location.y),u.location.y>i&&(i=u.location.y)}a.x1=t,a.x2=r,a.y1=n,a.y2=i}};return n.setSpringForce(i),n.setNbodyForce(r),n.setDragForce(o),b(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=n.run(t.timeStep);return N(),t.stableThreshold>e},isNodePinned:function(e){var t=c(e.id);return t?p(t):void 0},pinNode:function(e,t){var n=c(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=c(e);return t||(m(e),t=c(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=c(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return a},dispose:function(){e.removeEventListener("change",V)},springLength:function(e){return 1===arguments.length?(i.options({length:e}),this):i.options().length},springCoeff:function(e){return 1===arguments.length?(i.options({coeff:e}),this):i.options().coeff},gravity:function(e){return 1===arguments.length?(r.options({gravity:e}),this):r.options().gravity},theta:function(e){return 1===arguments.length?(r.options({theta:e}),this):r.options().theta},drag:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a="function"==typeof Object.create?Object.create(null):{},u=function(e){e&&(a[e.id]=i(e),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];n.node&&("add"===n.changeType?u(n.node):delete a[n.node.id])}};return e.addEventListener("changed",f),{run:function(){this.step()},step:function(){return s(),!0},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=void 0!==t.interactive?t.interactive:!0,d=!1,l=!0,h=0,v=0,p=!1,m=!1,g=!1,y={x:0,y:0},x={offsetX:0,offsetY:0,scale:1},w=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},V=Viva.Graph.Utils.events(window),b=Viva.Graph.Utils.events({}).extend(),N=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},P=function(){return p=u.step()&&!m,N(),!p},E=function(e){return i?(v+=e,void 0):(e?(v+=e,i=Viva.Graph.Utils.timer(function(){return P()},n)):(h=0,v=0,i=Viva.Graph.Utils.timer(P,n)),void 0)},G=function(){g||(p=!1,i.restart())},L=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},_=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);y.x=y.y=0,x.offsetX=t.width/2-(e.x2+e.x1)/2,x.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(x.offsetX,x.offsetY),l=!1},A=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},I=function(e){s.releaseNode(e)},k=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},T=function(e){s.releaseLink(e)},C=function(e){var t=!1,n="string"==typeof c&&-1!==c.indexOf("node")||c;n&&r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),m=!0,G()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/x.scale,r.y+n.y/x.scale),m=!0,N()},onStop:function(){u.pinNode(e,t),m=!1}})},S=function(e){r.bindDragNDrop(e,null)},M=function(){s.init(f),e.forEachNode(A),t.renderLinks&&e.forEachLink(k)},U=function(){s.release(f)},D=function(t){var n=t.node;"add"===t.changeType?(A(n),C(n),l&&_()):"remove"===t.changeType?(S(n),I(n),0===e.getNodesCount()&&(l=!0)):"update"===t.changeType&&(S(n),I(n),A(n),C(n))},R=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&k(n);else if("remove"===e.changeType)t.renderLinks&&T(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},O=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?D(n):n.link&&R(n);G()},F=function(){_(),P()},z=function(){a&&(a.release(),a=null)},B=function(){o&&(o.stop("changed",O),o=null)},Y=function(e,t){if(!t){var n=Viva.Graph.Utils.getDimension(f);t={x:n.width/2,y:n.height/2}}var r=Math.pow(1.4,e?-.2:.2);return x.scale=s.scale(r,t),N(),b.fire("scale",x.scale),x.scale},X=function(){V.on("resize",F),z();var t="string"==typeof c&&-1!==c.indexOf("drag")||c;t&&(a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){y.x+=t.x,y.y+=t.y,s.translateRel(t.x,t.y),N()}));var n="string"==typeof c&&-1!==c.indexOf("scroll")||c;n&&a.onScroll(function(e,t,n){Y(0>t,n)}),e.forEachNode(C),B(),o=Viva.Graph.Utils.events(e),o.on("changed",O)},q=function(){d=!1,B(),z(),V.stop("resize",F),b.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&T(e)}),e.forEachNode(function(e){S(e),I(e)}),u.dispose(),U()};return{run:function(e){return d||(w(),L(),_(),M(),X(),d=!0),E(e),this},reset:function(){s.resetScale(),_(),x.scale=1},pause:function(){g=!0,i.stop()},resume:function(){g=!1,i.restart()},rerender:function(){return N(),this},zoomOut:function(){return Y(!0)},zoomIn:function(){return Y(!1)},moveTo:function(e,t){s.graphCenterChanged(x.offsetX-e*x.scale,x.offsetY-t*x.scale),N()},getGraphics:function(){return s},dispose:function(){q()},on:function(e,t){return b.addEventListener(e,t),this},off:function(e,t){return b.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r); +return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},d=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},l=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?d(e):(d=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,l()},translateRel:function(e,r){t+=e,n+=r,l()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,l()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),d=f.attr("id"),l=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&d===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&l===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){function e(){var e=Viva.Graph.svg("svg");return t=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),e.appendChild(t),e}var t,n,r,i,o,a=1,u={},s={},f=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},c=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},d=function(){return Viva.Graph.svg("line").attr("stroke","#999")},l=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},h=function(e){e.fire("rescaled")},v={x:0,y:0},p={x:0,y:0},m={x:0,y:0},g=function(){if(t){var e="matrix("+a+", 0, 0,"+a+","+r+","+i+")";t.attr("transform",e)}};n=e();var y={getNodeUI:function(e){return u[e]},getLinkUI:function(e){return s[e]},node:function(e){return"function"==typeof e?(f=e,this):void 0},link:function(e){return"function"==typeof e?(d=e,this):void 0},placeNode:function(e){return c=e,this},placeLink:function(e){return l=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){r=e,i=t,g()},inputManager:Viva.Input.domInputManager,translateRel:function(e,r){var i=n.createSVGPoint(),o=t.getCTM(),a=n.createSVGPoint().matrixTransform(o.inverse());i.x=e,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";t.attr("transform",u)},scale:function(e,o){var u=n.createSVGPoint();u.x=o.x,u.y=o.y,u=u.matrixTransform(t.getCTM().inverse());var s=n.createSVGMatrix().translate(u.x,u.y).scale(e).translate(-u.x,-u.y),f=t.getCTM().multiply(s);a=f.a,r=f.e,i=f.f;var c="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return t.attr("transform",c),h(this),a},resetScale:function(){a=1;var e="matrix(1, 0, 0, 1, 0, 0)";return t.attr("transform",e),h(this),this},init:function(e){e.appendChild(n),g(),"function"==typeof o&&o(n)},release:function(e){n&&e&&e.removeChild(n)},addLink:function(e,n){var r=d(e);if(r)return r.position=n,r.link=e,s[e.id]=r,t.childElementCount>0?t.insertBefore(r,t.firstChild):t.appendChild(r),r},releaseLink:function(e){var n=s[e.id];n&&(t.removeChild(n),delete s[e.id])},addNode:function(e,n){var r=f(e);if(r)return r.position=n,r.node=e,u[e.id]=r,t.appendChild(r),r},releaseNode:function(e){var n=u[e.id];n&&(t.removeChild(n),delete u[e.id])},renderNodes:function(){for(var e in u)if(u.hasOwnProperty(e)){var t=u[e];v.x=t.position.x,v.y=t.position.y,c(t,v,t.node)}},renderLinks:function(){for(var e in s)if(s.hasOwnProperty(e)){var t=s[e];p.x=t.position.from.x,p.y=t.position.from.y,m.x=t.position.to.x,m.y=t.position.to.y,l(t,p,m,t.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):o=e),n},getSvgRoot:function(){return n}};return Viva.Graph.Utils.events(y).extend(),y},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,d=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(d.x)+" "+Math.round(d.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),l=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),v=new Float32Array(h),p=new Uint32Array(h),m=0,g=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(p),v=t,p=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(l,d),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;v[n*f]=t.x,v[n*f+1]=t.y,v[n*f+2]=e.size,p[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(p,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,d=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),v=0,p=new ArrayBuffer(16*d),m=new Float32Array(p),g=new Uint32Array(p),y=function(){if((v+1)*d>p.byteLength){var e=new ArrayBuffer(2*p.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,p=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,l),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),v+=1,o=e.id},removeLink:function(e){v>0&&(v-=1),v>e.id&&v>0&&r.copyArrayPart(g,e.id*c,v*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,p,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*v),o=v-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},d=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},l=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},v=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},p=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=l(e),o={offset:e};r.textureNumber>=s.length&&d();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=l(t.offset),r=l(o);p(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],v(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){v(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,d=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),l=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,v=0,p=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(l,d),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;p[n]=t.x-e.size,p[n+1]=t.y-e.size,p[n+2]=4*e._offset,p[n+3]=t.x+e.size,p[n+4]=t.y-e.size,p[n+5]=4*e._offset+1,p[n+6]=t.x-e.size,p[n+7]=t.y+e.size,p[n+8]=4*e._offset+2,p[n+9]=t.x-e.size,p[n+10]=t.y+e.size,p[n+11]=4*e._offset+2,p[n+12]=t.x+e.size,p[n+13]=t.y-e.size,p[n+14]=4*e._offset+1,p[n+15]=t.x+e.size,p[n+16]=t.y+e.size,p[n+17]=4*e._offset+3},createNode:function(t){p=i.extendArray(p,v,c),v+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){v>0&&(v-=1),v>t.id&&v>0&&(t.src&&e.remove(t.src),i.copyArrayPart(p,t.id*c,v*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,p,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*v)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f=0,c=0,d=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],l=[],h=[],v={},p={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(d),g.updateTransform(d)},V=function(){d=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},N=function(e){e.fire("rescaled")};n=window.document.createElement("canvas");var P={getLinkUI:function(e){return p[e]},getNodeUI:function(e){return v[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return a=e,this},placeLink:function(e){return u=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){c>0&&m.render(),f>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(e,t){d[12]=2*e/i-1,d[13]=1-2*t/o,w()},addLink:function(e,t){var n=c++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,p[e.id]=r,r},addNode:function(e,t){var n=f++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),l[n]=r,v[e.id]=r,r},translateRel:function(e,t){d[12]+=2*d[0]*e/i/d[0],d[13]-=2*d[5]*t/o/d[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=d[12],r-=d[13],d[12]+=n*(1-e),d[13]+=r*(1-e),d[0]*=e,d[5]*=e,w(),N(this),d[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var f="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(f),f}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof s&&s(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){c>0&&(c-=1);var t=p[e.id];delete p[e.id],m.removeLink(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=h[c];h[n]=r,r.id=n}},releaseNode:function(e){f>0&&(f-=1);var t=v[e.id];delete v[e.id],g.removeNode(t);var n=t.id;if(f>n){if(0===f||f===n)return;var r=l[f];l[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;f>t;++t){var n=l[t];e.x=n.position.x,e.y=-n.position.y,a&&a(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;c>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,u&&u(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):s=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-d[12])/d[0],e.y=(e.y-d[13])/d[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;f>n;++n)if(t(l[n],e.x,e.y))return l[n].node;return null}};return Viva.Graph.Utils.events(P).extend(),P},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},i=function(t){return e.getNodeAtClientPos(t,r)},o=null,a=[],u=[],s=[],f=[],c=[],d=[],l=[],h=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},p=function(e){return v(e),!1},m=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(e){var r={x:0,y:0},g=null,y=+new Date,x=function(e){m(c,[g,e]),r.x=e.clientX,r.y=e.clientY},w=function(){h.stop("mousemove",x),h.stop("mouseup",w)},V=function(){n=e.getBoundingClientRect()};window.addEventListener("resize",V),V(),e.addEventListener("mousemove",function(e){if(!o){var t,s=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,t=i(r),t&&g!==t?(g=t,s=s||m(a,[g])):null===t&&g!==t&&(s=s||m(u,[g]),g=null),s&&v(e)}}),e.addEventListener("mousedown",function(e){var o,a=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]?(a=m(s,o),h.on("mousemove",x),h.on("mouseup",w),t=window.document.onselectstart,window.document.onselectstart=p,g=o[0]):g=null,a&&v(e)}),e.addEventListener("mouseup",function(e){var o,a=+new Date;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]&&(window.document.onselectstart=t,400>a-y&&o[0]===g?m(l,o):m(d,o),y=a,m(f,o)&&v(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&l.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file diff --git a/src/View/svgGraphics.js b/src/View/svgGraphics.js index 3e25683..9e2b511 100644 --- a/src/View/svgGraphics.js +++ b/src/View/svgGraphics.js @@ -61,6 +61,8 @@ Viva.Graph.View.svgGraphics = function () { } }; + svgRoot = createSvgRoot(); + var graphics = { getNodeUI: function (nodeId) { return allNodes[nodeId]; @@ -199,12 +201,6 @@ Viva.Graph.View.svgGraphics = function () { * provider prepare to render. */ init : function (container) { - svgRoot = Viva.Graph.svg("svg"); - - svgContainer = Viva.Graph.svg("g") - .attr("buffered-rendering", "dynamic"); - - svgRoot.appendChild(svgContainer); container.appendChild(svgRoot); updateTransform(); // Notify the world if someoen waited for update. TODO: should send an event @@ -339,8 +335,19 @@ Viva.Graph.View.svgGraphics = function () { } }; + // Let graphics fire events before we return it to the caller. Viva.Graph.Utils.events(graphics).extend(); return graphics; + + function createSvgRoot() { + var svgRoot = Viva.Graph.svg("svg"); + + svgContainer = Viva.Graph.svg("g") + .attr("buffered-rendering", "dynamic"); + + svgRoot.appendChild(svgContainer); + return svgRoot; + } }; diff --git a/src/View/webglGraphics.js b/src/View/webglGraphics.js index b053197..ec36dd1 100644 --- a/src/View/webglGraphics.js +++ b/src/View/webglGraphics.js @@ -12,7 +12,7 @@ Viva.Graph.View = Viva.Graph.View || {}; * * @param options - to customize graphics behavior. Currently supported parameter * enableBlending - true by default, allows to use transparency in node/links colors. - * preserveDrawingBuffer - false by default, tells webgl to preserve drawing buffer. + * preserveDrawingBuffer - false by default, tells webgl to preserve drawing buffer. * See https://www.khronos.org/registry/webgl/specs/1.0/#5.2 */ @@ -87,6 +87,8 @@ Viva.Graph.View.webglGraphics = function (options) { graphics.fire("rescaled"); }; + graphicsRoot = window.document.createElement("canvas"); + var graphics = { getLinkUI: function (linkId) { return allLinks[linkId]; @@ -158,7 +160,7 @@ Viva.Graph.View.webglGraphics = function (options) { * Called every time before renderer starts rendering. */ beginRender : function () { - // this function could be replaced by this.init, + // this function could be replaced by this.init, // based on user options. }, @@ -293,7 +295,6 @@ Viva.Graph.View.webglGraphics = function (options) { container = c; - graphicsRoot = window.document.createElement("canvas"); updateSize(); resetScaleInternal(); container.appendChild(graphicsRoot); @@ -512,7 +513,7 @@ Viva.Graph.View.webglGraphics = function (options) { getNodeAtClientPos: function (clientPos, preciseCheck) { if (typeof preciseCheck !== "function") { // we don't know anything about your node structure here :( - // potentially this could be delegated to node program, but for + // potentially this could be delegated to node program, but for // right now, we are giving up if you don't pass boundary check // callback. It answers to a question is nodeUI covers (x, y) return null; diff --git a/src/version.js b/src/version.js index 46aad75..67454a9 100644 --- a/src/version.js +++ b/src/version.js @@ -1 +1 @@ -Viva.Graph.version = '0.5.72'; +Viva.Graph.version = '0.5.8'; From 316c0f2850431225936d269cb793679336394a92 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 28 Sep 2014 17:29:35 -0700 Subject: [PATCH 094/276] 0.5.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8144c6c..83cd306 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.5.6", + "version": "0.5.8", "description": "Graph Drawing Library", "main": "dist/vivagraph", "directories": { From e8005e3f3269b9ac00e32c952aeb05f8a612a82d Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 8 Oct 2014 01:47:47 -0700 Subject: [PATCH 095/276] Added example with area select tool --- demos/other/webgl-area-select/index.html | 42 ++++++++ demos/other/webgl-area-select/index.js | 127 +++++++++++++++++++++++ 2 files changed, 169 insertions(+) create mode 100644 demos/other/webgl-area-select/index.html create mode 100644 demos/other/webgl-area-select/index.js diff --git a/demos/other/webgl-area-select/index.html b/demos/other/webgl-area-select/index.html new file mode 100644 index 0000000..1517c1e --- /dev/null +++ b/demos/other/webgl-area-select/index.html @@ -0,0 +1,42 @@ + + + + + + VivaGraphs WebGL Mouse Input test page + + + + + + + + +
+
+ + Use mouse to draw rectangle and select nodes + + + diff --git a/demos/other/webgl-area-select/index.js b/demos/other/webgl-area-select/index.js new file mode 100644 index 0000000..6af7e07 --- /dev/null +++ b/demos/other/webgl-area-select/index.js @@ -0,0 +1,127 @@ +function onLoad() { + var graphGenerator = Viva.Graph.generator(); + var graph = graphGenerator.grid(50, 10); + + var layout = Viva.Graph.Layout.forceDirected(graph); + + var graphics = Viva.Graph.View.webglGraphics(); + + var renderer = Viva.Graph.View.renderer(graph, { + layout: layout, + graphics: graphics, + container: document.getElementById('graph-container') + }); + + renderer.run(); + + // we are calling this immediately, but this should probably be triggered by + // a "tool" button, where users can select ractangular nodes + selectNodes(graph, renderer, layout); +} + +function selectNodes(graph, renderer, layout) { + var graphics = renderer.getGraphics(); + var overlay = createOverlay(document.querySelector('.graph-overlay'), document.getElementById('graph-container')); + overlay.onAreaSelected(function(area) { + // For the sake of this demo we are using silly O(n) implementation. + // Could be improved with spatial indexing if required. + var topLeft = graphics.transformClientToGraphCoordinates({ + x: area.x, + y: area.y + }); + + var bottomRight = graphics.transformClientToGraphCoordinates({ + x: area.x + area.width, + y: area.y + area.height + }); + + graph.forEachNode(higlightIfInside); + renderer.rerender(); + + return; + + function higlightIfInside(node) { + var nodeUI = graphics.getNodeUI(node.id) + if (isInside(node.id, topLeft, bottomRight)) { + nodeUI.color = 0xFFA500ff; + nodeUI.size = 20; + } else { + nodeUI.color = 0x009ee8ff; + nodeUI.size = 10; + } + } + + function isInside(nodeId, topLeft, bottomRight) { + var nodePos = layout.getNodePosition(nodeId); + return (topLeft.x < nodePos.x && nodePos.x < bottomRight.x && + topLeft.y < nodePos.y && nodePos.y < bottomRight.y); + } + }); +} + +function createOverlay(overlayDom, underElement) { + var selectionIndicator = document.createElement('div'); + selectionIndicator.className = 'graph-selection-indicator'; + overlayDom.appendChild(selectionIndicator); + + var notify = []; + var dragndrop = Viva.Graph.Utils.dragndrop(overlayDom); + var selectedArea = { + x: 0, + y: 0, + width: 0, + height: 0 + }; + var startX = 0; + startY = 0; + + dragndrop.onStart(function(e) { + startX = selectedArea.x = e.clientX; + startY = selectedArea.y = e.clientY; + selectedArea.width = selectedArea.height = 0; + + updateSelectedAreaIndicator(); + selectionIndicator.style.display = 'block'; + }); + + dragndrop.onDrag(function(e) { + recalculateSelectedArea(e); + updateSelectedAreaIndicator(); + notifyAreaSelected(); + }); + + dragndrop.onStop(function(e) { + selectionIndicator.style.display = 'none'; + }); + + dragndrop.onScroll(function (e) { + // instead of eating this event, let's propagate it to the renderer + var dispatched = new WheelEvent(e.type, e); + underElement.dispatchEvent(dispatched); + }); + return { + onAreaSelected: function(cb) { + notify.push(cb); + } + } + + function notifyAreaSelected() { + notify.forEach(function(cb) { + cb(selectedArea); + }); + } + + function recalculateSelectedArea(e) { + selectedArea.width = Math.abs(e.clientX - startX); + selectedArea.height = Math.abs(e.clientY - startY); + selectedArea.x = Math.min(e.clientX, startX); + selectedArea.y = Math.min(e.clientY, startY); + } + + function updateSelectedAreaIndicator() { + selectionIndicator.style.left = selectedArea.x + 'px'; + selectionIndicator.style.top = selectedArea.y + 'px'; + selectionIndicator.style.width = selectedArea.width + 'px'; + selectionIndicator.style.height = selectedArea.height + 'px'; + } +} From 8342dfb9d41fb619ec2e3a505beb508ce7743873 Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 8 Oct 2014 01:48:26 -0700 Subject: [PATCH 096/276] Added comment --- demos/other/webgl-area-select/index.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/demos/other/webgl-area-select/index.js b/demos/other/webgl-area-select/index.js index 6af7e07..f0569d9 100644 --- a/demos/other/webgl-area-select/index.js +++ b/demos/other/webgl-area-select/index.js @@ -1,3 +1,7 @@ +/** + * this demo shows one possible way of implementing "area" selection with webgl + * renderer + */ function onLoad() { var graphGenerator = Viva.Graph.generator(); var graph = graphGenerator.grid(50, 10); From 38f60b27a635ced609c3e5c8e45aa88532ce3346 Mon Sep 17 00:00:00 2001 From: Andrei Kashcha Date: Wed, 8 Oct 2014 01:50:36 -0700 Subject: [PATCH 097/276] Create README.md --- demos/other/webgl-area-select/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 demos/other/webgl-area-select/README.md diff --git a/demos/other/webgl-area-select/README.md b/demos/other/webgl-area-select/README.md new file mode 100644 index 0000000..0cc41bf --- /dev/null +++ b/demos/other/webgl-area-select/README.md @@ -0,0 +1 @@ +This demo shows how to implement rectangular selection tool with webgl renderer From a713150e4cc4902409998569a636c8a2dcfb84e7 Mon Sep 17 00:00:00 2001 From: Andrei Kashcha Date: Wed, 8 Oct 2014 02:01:56 -0700 Subject: [PATCH 098/276] Update README.md --- demos/other/webgl-area-select/README.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/demos/other/webgl-area-select/README.md b/demos/other/webgl-area-select/README.md index 0cc41bf..ac6a3fe 100644 --- a/demos/other/webgl-area-select/README.md +++ b/demos/other/webgl-area-select/README.md @@ -1 +1,18 @@ -This demo shows how to implement rectangular selection tool with webgl renderer +# Select nodes inside area + +This demo shows how to implement rectangular selection tool with webgl renderer. [Click here](http://anvaka.github.io/VivaGraphJS/demos/other/webgl-area-select/) to see it in action. + +# How it is done? + +First of all we create a basic div overlay on top of graph container: + +``` html +
+
+``` + +Overlay element should have exactly the same size/position as grpah container. In this demo we are using absolute position for `.graph-overlay` and explicitly positioned common parent (`body`). See more details here: [How to overlay one div over another div](http://stackoverflow.com/questions/2941189/how-to-overlay-one-div-over-another-div). + +After this is done we are using vivagraph methods to track drag'n'drop actions, and convert [client coordinates into graph coordinates](https://github.com/anvaka/VivaGraphJS/blob/8342dfb9d41fb619ec2e3a505beb508ce7743873/demos/other/webgl-area-select/index.js#L32-L40). + +Finally we are doing linear iteration over all nodes within graph and ask layout to provide their coordinates. If those coordinates are [within bounding rectangle](https://github.com/anvaka/VivaGraphJS/blob/8342dfb9d41fb619ec2e3a505beb508ce7743873/demos/other/webgl-area-select/index.js#L58-L62), we higlight the node. From 7dbd4a8820b02a155d3d760b334fb5361d70bba5 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 11 Oct 2014 13:35:03 -0700 Subject: [PATCH 099/276] Use shift to select multiple nodes --- demos/other/webgl-area-select/index.html | 3 +- demos/other/webgl-area-select/index.js | 49 ++++++++++++++++-------- 2 files changed, 36 insertions(+), 16 deletions(-) diff --git a/demos/other/webgl-area-select/index.html b/demos/other/webgl-area-select/index.html index 1517c1e..950692d 100644 --- a/demos/other/webgl-area-select/index.html +++ b/demos/other/webgl-area-select/index.html @@ -22,7 +22,8 @@ left: 0; top: 0; width: 100%; - height: 100% + height: 100%; + display: none; } .graph-selection-indicator { position: absolute; diff --git a/demos/other/webgl-area-select/index.js b/demos/other/webgl-area-select/index.js index f0569d9..994c346 100644 --- a/demos/other/webgl-area-select/index.js +++ b/demos/other/webgl-area-select/index.js @@ -15,18 +15,32 @@ function onLoad() { graphics: graphics, container: document.getElementById('graph-container') }); + var multiSelectOverlay; renderer.run(); - // we are calling this immediately, but this should probably be triggered by - // a "tool" button, where users can select ractangular nodes - selectNodes(graph, renderer, layout); + document.addEventListener('keydown', function(e) { + if (e.which === 16 && !multiSelectOverlay) { // shift key + multiSelectOverlay = startMultiSelect(graph, renderer, layout); + } + }); + document.addEventListener('keyup', function(e) { + if (e.which === 16 && multiSelectOverlay) { + multiSelectOverlay.destroy(); + multiSelectOverlay = null; + } + }) } -function selectNodes(graph, renderer, layout) { +function startMultiSelect(graph, renderer, layout) { var graphics = renderer.getGraphics(); - var overlay = createOverlay(document.querySelector('.graph-overlay'), document.getElementById('graph-container')); - overlay.onAreaSelected(function(area) { + var domOverlay = document.querySelector('.graph-overlay') + var overlay = createOverlay(domOverlay, document.getElementById('graph-container')); + overlay.onAreaSelected(handleAreaSelected); + + return overlay; + + function handleAreaSelected(area) { // For the sake of this demo we are using silly O(n) implementation. // Could be improved with spatial indexing if required. var topLeft = graphics.transformClientToGraphCoordinates({ @@ -60,13 +74,17 @@ function selectNodes(graph, renderer, layout) { return (topLeft.x < nodePos.x && nodePos.x < bottomRight.x && topLeft.y < nodePos.y && nodePos.y < bottomRight.y); } - }); + } } function createOverlay(overlayDom, underElement) { - var selectionIndicator = document.createElement('div'); - selectionIndicator.className = 'graph-selection-indicator'; - overlayDom.appendChild(selectionIndicator); + var selectionClasName = 'graph-selection-indicator'; + + if (!overlayDom.querySelector('.' + selectionClasName)) { + var selectionIndicator = document.createElement('div'); + selectionIndicator.className = selectionClasName; + overlayDom.appendChild(selectionIndicator); + } var notify = []; var dragndrop = Viva.Graph.Utils.dragndrop(overlayDom); @@ -98,14 +116,15 @@ function createOverlay(overlayDom, underElement) { selectionIndicator.style.display = 'none'; }); - dragndrop.onScroll(function (e) { - // instead of eating this event, let's propagate it to the renderer - var dispatched = new WheelEvent(e.type, e); - underElement.dispatchEvent(dispatched); - }); + overlayDom.style.display = 'block'; + return { onAreaSelected: function(cb) { notify.push(cb); + }, + destroy: function () { + overlayDom.style.display = 'none'; + dragndrop.release(); } } From 4b57a2b2d35bea828e54ccc597f58e413867f291 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 11 Oct 2014 13:36:03 -0700 Subject: [PATCH 100/276] Updated documentations --- demos/other/webgl-area-select/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demos/other/webgl-area-select/index.html b/demos/other/webgl-area-select/index.html index 950692d..abeb3e4 100644 --- a/demos/other/webgl-area-select/index.html +++ b/demos/other/webgl-area-select/index.html @@ -37,7 +37,7 @@
- Use mouse to draw rectangle and select nodes + Use Shift + Mouse to draw rectangle and select nodes From 7521668dfcf8eb68086c7d707a8b39ed9543cae6 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 11 Oct 2014 18:33:26 -0700 Subject: [PATCH 101/276] No need to show scrollbars --- demos/other/webGLRenderer.html | 1 + 1 file changed, 1 insertion(+) diff --git a/demos/other/webGLRenderer.html b/demos/other/webGLRenderer.html index e306bc6..d20edbc 100644 --- a/demos/other/webGLRenderer.html +++ b/demos/other/webGLRenderer.html @@ -45,6 +45,7 @@ height: 100%; width: 100%; position: absolute; + overflow: hidden; } canvas { width: 100%; From d92295d3cf137b93102bac0af11cac5af15c77b5 Mon Sep 17 00:00:00 2001 From: anvaka Date: Thu, 16 Oct 2014 00:07:02 -0700 Subject: [PATCH 102/276] Added example with clear-color This should also fix https://github.com/anvaka/VivaGraphJS/issues/106 --- demos/other/webgl-clear-color/README.md | 14 ++++++ demos/other/webgl-clear-color/clear.png | Bin 0 -> 12417 bytes demos/other/webgl-clear-color/dirty.png | Bin 0 -> 219611 bytes demos/other/webgl-clear-color/index.html | 52 +++++++++++++++++++++++ 4 files changed, 66 insertions(+) create mode 100644 demos/other/webgl-clear-color/README.md create mode 100644 demos/other/webgl-clear-color/clear.png create mode 100644 demos/other/webgl-clear-color/dirty.png create mode 100644 demos/other/webgl-clear-color/index.html diff --git a/demos/other/webgl-clear-color/README.md b/demos/other/webgl-clear-color/README.md new file mode 100644 index 0000000..3337ed2 --- /dev/null +++ b/demos/other/webgl-clear-color/README.md @@ -0,0 +1,14 @@ +# Clear color + +By default webgl renderer will not clear the scene. This may result in artifacts +![dirty](https://raw.githubusercontent.com/anvaka/VivaGraphJS/master/demos/other/webgl-clear-color/dirty.png) + +Instead of expected + +![clear](https://raw.githubusercontent.com/anvaka/VivaGraphJS/master/demos/other/webgl-clear-color/clear.png) + +This demo shows how to set clear color in webgl renderer. [Click here](http://anvaka.github.io/VivaGraphJS/demos/other/webgl-clear-color/) to see it in action. + +# How it is done? + +See the source code if [index.html](index.html) diff --git a/demos/other/webgl-clear-color/clear.png b/demos/other/webgl-clear-color/clear.png new file mode 100644 index 0000000000000000000000000000000000000000..cba92ed1cb2d18dcd1a6e016e1ffef42a3c77fc2 GIT binary patch literal 12417 zcmeHsWl&vRlkS1wn&1*7xVw9Bg1bY|gF75tLU4D7;C^rj?hy3g1lNN*!EN$>Gk4~z zy1(!JHLGgx>fNiKw%S!|b$5h{k_#n0=*s`&&z|sF+0t5odfxe`XqkTf7MvF44+#IzVwIOtv+oCLtH1HCzow&uJvtCNdez=tS>Lw z=@0>R&T?oVeN<;-(E#T@c`*Qv7+jlJ23{tC+$-exiA^j$M1ny<|E+ZS&8UYE zFP8uXu#FNW(T62r_DKX2kjl)Jn*av@V~!T9C2ePTVwpN1P$6AXV9QjQ3Yla6l<+q> z)Fe>`$pbDP0q=FKxuoF$c3LVdxmZLnr?nxy95x07!Wdfe!M~}v5)mxEk*LV<^LS8V zcZcYR?24X9J|mV)i@z=xO;fyX8+Y|&Ui54I8Mr6VdpsI@+o$BAAsn*3Neon8kPXcd ze1?WP3lelrCq(Fe5+T9guE#TF7+7;Vn08zx%dp#rXIBs4;+n=9!nzQDW{$RmBGs`0 z=;-;E$DVmpi`mKb=4F@<v+uypB$g8Gz_9q8~nrs5B7dJJ&FFL5}ICqH~I;Y z%jVtM5UFW8W1|S=%q*hmFYHsAhjJqi6P_qe%L%dn(it zk`jMu-*KC#P$72eE%s)GR;q!f2zt_hBO_%~PYx)XL;4n7=DUVY@yYbNOF8g(I@`lD zK&b~y2gW%b?fiZ12T2(3x8d8ki&O0g^dB$?;eahMXv?lLdft2@-~Ar|;U;!?us}q> zv2ImrXfO_)@gw7lrZ&8t4zr?e^#}CzUe*Cq_&ORL$|`K%%wB!$$~f+Ob>-|AOyv&l zbri?2mR`o^gg}*F0toA9VsFOgv9(Mey@vxKKSf2JZ87gK?f`cPcSyXEKCm6VE1Hbm z!srG2?5}M1wo8Q3;kyb|JBi~;sEc9Qh=^eBbrtcD32H;PyP2|wwe^U(pW3cw@4#k`+; zm9*#i8)MWmTwpH2$9LdYMpQC{AII-tD7Dyo7#k&G{ed~}ei6`8pjr^>u>YxFaA~mn#H}}z9 zQg~X73szB#bIP}ofLX?Nil!0$^z-?TxGB{??*yV?2slFVDT7pd56qa@ZP{Pb(FqV} zP#fNN8F4l_}woi zXNYBoj?W|;Yw|rX?s`yaQ_UIvCx-zE7#D5?SZU(nsz-K^ckT`w($N{UKqTYxQxE&DO@0%Mi3PPZBzj&3C3U|ymm zeF>KeSj|Yyzt*{~ynd-6q|Ty2v#zNQz246fXp&~a3p9r0_8JZO$G(U>$zb4N=wirY z5Xs=l;L6Yro5kuXu_&QWHf7gk3-S~5J31?=A#3PXaC1jzDho?@ej(ZEbCPq`bqR5? z->QJN4RKG#?5FND@5gSlY&-0o?dR_0Us+vyUKd?zTpH{WLI*EKua>WeF3$FZ#{|cp zl9azgvRSih;?Hq5$TvQAzwagt;CsV(#e0=`7KI;xuYxatzeQ<8?RY~iZu=t2w4 z9aG;`gkta7?vgQV;{L%cz^%YVz)_VV8I&Dl7<~FtmI%f&EY~{>;!s)=<5y~xeyBsK zjBNc9IVzX3SkY0TRN+-|T9G$jH2*w*Td}61ueGQer&^;KQ1W@+Y3kSP!A$zJ#vIyw z)r@bM)O7vy=)%#|V?lKh3D{58M>0%)SQnV3R5O_f&SjCfOFm1^Z8WM~|J*tJxcUfw z6ufaH+C*bQt4D7`-$QptPeOwby_yx7;@HnwakWZ2DBfo-bDIq%4sq=i4i(aD)AZ8F zC`c<(D_ECsmpG0WjrWZojnj9aBEG4C;at$kuB5^ES^{C%xBR z-FILFVBlf;gIt2FgIX3)!Ew3)?BT-Ucy25N_$Sz_1Rb*a@|F1$p})gEqGez-p$Wf# z{4~yFXZ%~^r?aQr{Q$xaIyEs3Wi;g%$`T4i$}tMj8Ro;3Kdh=As$qqD1&h*o;YJac z5!MmZLkPnjL#jIkJC8h(4hk#xS~EY2j1|G#*sW{e#zQ<`28o zBQ@#@Y87h!Mc$>k@;eGq^6gpRbfa{U1d}9ZUu+NcgOc?LtSndF?ny3)P-cjEi204B zyv05+ZvXe*+dy{JyWvxcn}Yg+!JK?S$Mc!rnq9WVo)XS)4r^;+x0`nZr-bXaZ7p5j8>kA+ ztL9o8?ep%tNS?Y*F_!}>71~cOU}l1L-xWfYpd`36xIPScjFgOInz|ZIA8|xks&d^Zlt)VsA>7)_b(oEP)gv{zpL8bC+f#tpxH8-McC6Sj`g^P@>hFG8vI-&yKf(`4MzecHAD5(^U?1V*$aH6Y?5IU%ekYI~h}-O7<+i6cexL5~x{@Dvij z;^BCp+8aqLrB}w!g$fM|Z(M%cky?`9O5?7wQKoZ8l%p?smwwMVWk=?gt(YH-Qh3{Wtcf{j7zy_#112%~OfdjX;kfsWlv|mVbK?LtWY1?1X4K7o@`G1eRr?{bu z94atNcN#})Mk|RaW#fxeGj@u)`hJlM9Y%peHTr;u zO^@?JK}zQ=Gph3Vlc~iZ_W653lv)%@mQC3*{|&q%WwqpKzkpv`&CMRV4mx}c&f)>F ze#X!A$1JJLQXL$fRNZ-f(9&wNpAE0I=zh5SwiBL5f_~+e&4J~X!}-?s;TaTqy0de9 zyuW{b-aRSWBRUn(=@<{H6`bH7pqZmmpfzv~)`8Qe`s5Py%75hkr$3#zRy%i9hoqbF zQ_g33E@dp)$L!T47jk#AOo=v)N423HMdqv)AOi5vqM^6T{Zk7St4ox#i1zF5f;@cj z3Pno|{VuZsL*E(K(tL-00A#6CzS#6B`L;5(oNS72v0@55S3bjErf={0YtQLE;i`~w z*wbbr4sl^H=T{l4)$bJ@_bX3zdDs2&O6K5F(VP@M`~d$SiuuANg&hsm$FCs~XHfZ$ zG;XlxUGg8L+a<%wHvjXX|Fb{lzUl%H5u zTl8&_1Z9R*mPVu{@^)iR?nj-wc4xirFOXo+p(z-U5tx%yDeM%yAbEXQ#?~V4@{@4; z?pj2Yll01cr0S-x;AQ8XeJ;J`Y4fbnXCZBEs*|Y1!Q#aS^|W!xbQb_U>I^L@@@E-x zgm7*E-7U^XBSzgJ4d0miohluI9(jsSIYLYY;UdcfN7`%KQzN_2U+aOE=f3nNWN-ct z9G&m9pkUl%2FeNoM9#_<5(a+Xi(e6iB;3KndvT0&@Y!?~j`p6*KUb-y?fe+(Efx=N zIrAWg*&EA`KXPVFR^`qsema%5NUnkQ$fU48uZW*0yQS>%Ho7!Q^(myXU9t zGhTEd(g93sQ8e#lQG=(Sj=O8>Gn`HPxvVqBq~7jkZf7w=1Usj#ml?>=k??Y}b7Mc8 z$K9ugP0?9nwXTYBwSC#^0|;gme(GWOwKA-)7~$_AD<{CJ^hG#xJwBmC%yc0EiX~%e zAan1?Hh8liNu!T>+XD|jk-$3lIld{_CA<1t=XWz+AaYaUF&~H+qPU*sdkw4c8TS*h zN#-xh>362313uKGUt;C`5_1zWLMux?JQ#)SMCvC$r_5`-Px(Br*QDW&i0&N2KjB|3 zaLPo&YG@&>;V9X?L=Kr+k)5`(o(Q~TPts6F7=FW^SnJsMfT1;(^#hR!(a% zJ*M2L1Y-r71n}G7`VwIG9|x*Ogope4)rYRz7ZuOHy%z9k)Vz@ET*z1skb zVkeWF$nF%zgk+;kAT=QGqXjhQvrv4R36CwllOYMmh*b@Lz*_l`)-X+zOa1E5rxYqd z!G5WyW>hbCCH}?7#x&DrS;O02dWxo35tA1mxNMQHn^xc8a^fQ8f`295vN|r>&{RPl zpnu|VE}leEFO^)dlmh`7GCQnxIx3&7&tXYhKa2ciqLb%~S0Oe2peh$Z- zX*1zZ;XLCpF!t+HTie_=z%v2M%2 zV7fehjnj?fjnOG~TdG^UlZWS1_-4``&=L}6ycaFd zed*c0zqUHp6}Q;sIVo(i_qMo1?5fmr4C}Ot066ypcoK*ipam)jXNxWXHow61%mRME z;sRO;FyjFa-Pd7sY+Y!Bfmu!pm{~gGi?1 z>or;4>vB*j7t{8Jv za*Sw96}molM?XimM<2o{SWZw@QBhu=W#wr-WMv;D;a_y2L6E)$V zv80>B&(xaWb$8|7vS4Snk*mq4YTm^eply43K-%2NLS1@iectWSQ~YdHY&d^o(;^`n zyIR$%;nRF3<|j?rX}v~&Ju3t>%CmKta4_CD3^2JKydAslMDVLy1g%#6H1ugHew*nD z?v0Qc7#>pg5PrIy321bW7E;PO@K%1NyCZy7f01%4dCt19TQNB4n1l=tHbZ~RUrG?= zwo(Ohcp6&bb=*8nt$6;8h#;Qo2H+MwUJR78~9!Spqy7Us999i|6f zX?Wq*s59n;c?YvUV^>@tE#G?&Z0Ycs0m*G{Jd;$7RFg!QL!=BzC2Hl`$NKd`9ksTl zKTFHM-IoOU75KsZ!bjLPeD0x)aamdIxx>l($c`LjyvD@c-2jFussq{qiaF+NBv)a2 zZ}DgrFvF{1fs9LwMtox`n%rKsU5!DtZ@zeeX>DRwebXqBrZ6{&yCJ%SA}TZR)Lp>2 z4c^=R@eVyTrg71ZOT>c1%<^llBfB{@FvtFSeDYVXJTh<{*Vo#B%>xyUmZI{6J3X=? za?rZqfuoqP&^Q9JYQZ5xeVs5-)m8Fk&#sYHuPW+Ow1<*eZ}m0&^3_GS>Ov0dlM zZ18RK?Q{+5#zA+AtIX5c)2rFLV+8&%7Eu&GH0g?5A|ank(-p>vX>CW3E^eYXK4+^@ z=*!9QY2MyjUEca5bX?(Wam0~v<6*zi-*eLOb?N7Yzg&RVo6RfkW`-J%6+q%Ep=#g~ zFhiVwf|n6bM#ot5R;B~xKNPQOjq-C{cdV*m~7`JQKe@9?6B{XHMQdqDW;ha zdYLb2RPfbu#sE1C;*C7-!4}%zp-4o<=g>yI`&(aWr9_^s7)$fT>xrly8gpx$`W&nz zgl1mo^<9#nXeNQgdUr5M+zE;elAro|AZ1ZYPy)z(Wp)QJQH>VDsCK?xWd7 zkm2>vwEo=618DDT@J}}hlJAB2ul=nZ6UcB&u9XP0*X>rw$k?_vt5Idg2oW(sns*wH zv*VW|ztJ#8vNTcK=N-1wyFtex=y9f_TEq7x-i`J>7k`4c^jye`+>4iaki{pHt&xI3 z)4}cC#Pykl;;=Ebu|Lo~=ppWDN@EJ@_%p4;)QtHgDZr#Da5#=tTdQjnR*VkjtM&Ql zsQAR_=nVVM5l@Vslyu{_eYTX0H*AuQA<0F~A(!;-H?J4W9rk`DvL(UTzw-rTCs|!r z000&Hp9cnznN9F_{E%anR~i5i@)Y<>+FQ7pkbBzO zIk*aV3RC<`Lf|j`51W;O{9ht&w!#!TiYnw1jxHAD+$>xyY!o6WXJKRg zZ{2^PLjQ0DRIEKM>~tip?JXQ!|Jo4YWakw6m;C>=^FJ2<4XOJ-NDfZke@Fh?&VM0= zSpNy&-vav2Z2gP-H(eqqLahItdJz@L!BcZpNe!GE?O3TznsAiWe{&r_RDZ)a25IJw)dw7eqcaT#z>x!Bki-D6?*spr{Qs4QpSrLut9GykqW-Wxdj%Q%W4F(T zmq4Z1B#Mi5ISYj@Ua8F~=l17O)5Z=@^+Tu2Kkq#uf6^n1bzz(In2852AE^ViN-vgJ zSdH%2$fSqQGS~ii6i$oPsox`ou|F)Buxw{WV8!#bIIMXe&J_P$DJd!5onVPmV2t-I zFhM(|oEA8(0A)X&KlHJ~0yZqUwdZROzYU9f*pi{xO1c8hF6q zpxTJ{J}Xk)%AJ8!oy`Sea6CkkkR9~&8xIeUYElxccK-bAOSbr-xDD&HgPUg`DFR79sW z&9Ju6b#IVIeJzVdp6~&y$I<#b8={^Cg zP!B__OZk~X9;ik8hhTO1ua->dvdblbr$1lCH4E;E!E&ic?{$I$N9VEkiT1k|fp=9M zL<_RD=d+`A5QQhD#PA(*F(3Dj$*xx_%zx%gK*-4$Nf;~H>8eEygovA~R(=SNWtc9f z*xK#|`SWrjQJla@x~E`7%rE>dq$d`UlWjfTQUqKbtgSXqbU3fUG)lfmRqC*r7DP0e z6&K^oUvZ7dcd~*CY5?}F^mOXS>>evFX7Bkt{>E-5vrZ{7@8XK8Gh*EsVv`u)a7grr z*p_d6?XY;Cio}DwmL19JFjQjrI4*#>RiE{%;U_3=g`7uf(~3&X{^S^a?ov`wKL#8R zT#$p}mr5;EVdqH^`8BFJl|^Pc(FEIa<-mc`=)j^x&8RkyB8t0Ax^oB9YLDG`HzsS^ zXKPP6V>%LNJ_1&lg)36l^S)Js%F1f>a#;bwF|02$`IeAY_mYu}){qvB8p3 zq#C3`dKl6$$R)N| z!=0@XffTS-P2rQjAk-*w zL_Wd|D$d>~EKf1zSUk{NU4QxqghLCRJL-CQKP4KC7k4c;>Kk)7I(2`Wp$_-YUiq0I zd*qgOrNkl(p)SPoZ8zv^jq&mgewzPPR7!xMI|Ea5k4^4cH>0MnVgPW3zVhatHbD1j zH)t=7>2i%Z6@K}U$BHxCq9Vf3XelS(Mj|W^32R)QeGx_U%q%||^vS;i<01C7g zO&!-T%s(Ig%wb;qntS$hF`k_|tX7k$mulPm9?GJXN(4yTO;p_@_SWVBb37`cQ*i#f zx+M|LQnS5&ua)8uIsMk|NRmazM2zTLe@cMJbimk>UJ6m5u8~HA2NdKV@MgS5_VQfe zAelJ_oY8Ii^UV1aaJ>I0-{MbgDW%hP>942A5Iyo2VE++vsqo*cgE zn{np}yD|p6xZf~TKM!}$i@qQ$%j8J=3off}wVoD|CH0ml#LRy5ays4$(_l1u7;ft# zB6_<39oAV)t9)#1i)Kyg^_r875Q~$ULi*!P9KdsMFIuL@}^_qnD`^d z^!V>7+#VmzMjm}*OI7540{*5kVNZT@1T;N*Q9`A3^*E5A7BnFKjZ;Rt_H$pD$Y084G7^XgLD= zy2D+X#?#121`*Q{{ckSIBUovT%mnDh_Fj zp*nKI%4a~e$0psOn4^=5?H6!9ndWR)N@1G(X%!~P-8T4Pw{&-cwiNb(v{Bi5KcYV- zDQ00kXM)O!FNzw?zJ|qHz-X0TO!}yykev`A%ux17&8CaERk^@0H@p7biW}u}k*_;> zc{`okZCA;?7GZ3GZjmhr0>)?9=upVQ)RnQZ){KPDHf zIfodqf77y+0Z%x18^T{DqOG*gHdVmcHno=2fbsTcgl40`CskyR@$hA-A8hbk+U&Zp zhc^R0!8GcH1B++{cPkR)4nLD#WH2cZhs=_q<6$Lgo?whohO;R}RZjw_2$M$r}UN3e8?q`TG{r`Z+R zRNPVs2HWB6u=U*SLKV?53I=t@q9b+po*7T2bixfi>OOQK;GxR9){XD!2()*18hPv2 zn@xf7F$zO6VQ!_~`zK4bT}!iFdTNaSrn4x04e-eRETzr}WWVs+XU^MJdnIfOmNEGo z>1t`WHU%YGT6w*0Ru{>5t);qd<*_{JTLXS~QDmF9b4t!e!uWMt;5JiJY89@x#k5C( z>?b)$LyUMiX|93*S$^v=FMXpx5U_I5u=O^v(w35aEG6Tk&9J6kwyePG#K{=J2!uDK zSir6IXm+>a^!ac}yUQ#St+L1SN2DL)+ud0*5jVjs-y?sHX87P@$*)#$vVSUs6mH4} zlZ_hjPA!vBeR=As`s`!Ogq~TAtGda`Ty0pJGAj3m*EE|9hjiBd_M-gv#7Z7NW4a=e zt+mt4P=}XJlM|UB(&1rM_tr4^A#QgE+k++uy=Q-VM{dpMN^GCD)-SXAV5iQ7$K)@X z+H+ChmhQ9^JZ8I2idBW5#7T0!xMe+>{l3}se~yo;6lT(6j@74^2OY!n;4Ei$YsvoJ z6v)0<3{Klt7f~Za#00&wutV;%sv&lcwU5?Ksp6~3w#RJ0d_KE6f76q;s3cCRWZ_-m z{L&@Eq#|t63%`8Bl)~`gjX_mFZd_IO=k&~9m;AS1*H;v9I-#6A^fI4XQRL9(3(OaC zuz4RMDQUIQYt43~Z_^gc_gqAal{PugePxY5?tP+TrM~$d!l6a;U|1G7A0jX}!@O5V z#VXZog3M;g$<#V+2t0pjP?o-$)U+mi)F{?TDYpMGIj$>O@dq2fXt^aJkxG(NwqJ88 zf7yh2PBJ4^i>LkhbQ{jxe%1f7*squi8(LfpV76KHjfUFCWof zxVT1#M2F|F=@zmV3u&YZp7Uj&O`M$QNG)6RHr4c{HeKlT+A~L230z-5U#24es z+Bap*E2&x!EgMm?YJJt!)^eNLTBq)?rNE=B0_MFkQoEPdBEcP34Fy0o-gU;fZju$j zTP@_c^f>Eyde7>$4?ZS2J+UTi+1jhv>W%(54W{w^_`|Fo-p>y;@@1?z`i-hh?;dbN z+nvIf9St3&<1%TnSKj}1>;06pcf|J(cUaXW$INP=1yo!5gSp;eQoWd|*8SKp>~j4t zfkuYBc}3WqdvBX-bNkAbotf1qd+T=lolbL60KHQw%jhk_>I%l29_J=mR)gQg-{w|) z%o;6gtBN$|-KiJ%V(#=8FQHOofiw7FslisD=aL*U4qibW2Vwypz3Q`_nx9`9HZ?45 z@M4FO`f8JodgRG+qdY+FA{MMWKaKzXhsJ6j)5o&}GT*dFHw<3oHKoap;jz>C`VVs9xucV6I1Cn5{P> zdLG6va5)b|up|OGX8drJfQEm4562)YCZ58mR<8tvXC9zJ66-;dEnB8J-WW?Nqk&nj z#Pw!jP@0!a`TVN;X^gEH7S5_h>EM%<9GCm;k+PtP{P#%xneU`>^9@p!NnYYwW9Y{g zKDR6yZ|*cG^CLouqx;^rP-X*11e;%f{@ya*UXE8%Uyt7k1VINiuZPN29nXo8vteZZ zI(dwYjK`lZ7K!v@Px# literal 0 HcmV?d00001 diff --git a/demos/other/webgl-clear-color/dirty.png b/demos/other/webgl-clear-color/dirty.png new file mode 100644 index 0000000000000000000000000000000000000000..0c68df1ae98248d79c51f2fab242d899fca86f76 GIT binary patch literal 219611 zcmZ^~19W83(lFW`I};ld+xEn^?M!UjoY=NCv5kpsOeVI?mzjIN@BiOh>-Ab^_37PJ zwX15Ms$JM8TwYcT9tIl*006*ChzlzM0KksV%LxkNb3`3B>hlXz##~59UP4HSP~O4T z)ZEJC^AG4M4QF*_o#x*M(oFqdgj`)+C0r#_2;siMk;46mCyJn;qChqzBq9tGi2xc> z6Hyozg!$bOMTE_71YY?}J*>a{=ACk!e4Sjithv#$Ji`YBsheM2F;YMRe%edGxoW}M z>+$>A_elu=PzAu+1k%vcF>TL}kHOxjPF@%UQiFx4q_sXuRzGxmu+XzHVF24OkwSgQ zLPlTt5CO@wEZK2jfNI3iBE^L5G&f{J8we7pDwVFjM5#f&bP~dD*Osr zJR|tNS~x@WzOC2QlYZH+dOPrlsrh_7_HjVWMus(Hc^B^|w2St&ogmHX0Gv_DmxW~pc?kJZ@Rc^obPwt$1Au~(b9L;MJ-LXH zP;)_y_E6$JyZa}*QNfGt%Xek%DA;;$0q(>7Uv@A2EhIcMtDvJ_Az3UyH-_*HQ>h#H zh-c>@4S%7WiRXE?3yee9>lrpcCVWdbVDs`3ji@TUPB!^s&z{BAb$H+tWV`o6k zlzT@RQ&`_=y~{(2;VEygSM5%n6kcnRTQ zB>ltKB;86f&=^jM?|ZB(XXwVX$6%BChaw%czEf~A_2EjQdOVfk=@lT`gRBm;kA=JV zQi~)E^!OOQkGVWk3y04ILWBYS2<$cQ%E9L>#B)5}0xt_A_=+zYIdYC$Ogg@@lmii-k`WxoF!>g^#xXU=_IJ`9CK6)|E z9Krx&3L{=>dupWgYexNqg%i=c&xAK?{>(JwGXdUR!m-kEr0?eYvt%GL8K^0O{)-%p zoK(OWqPk6#oY^!nQNqB)9|~ML8v=~-a+>P0>O6RWqqNyE;Bvv+xl+{a;)6PJ70fRi z6Bo4lof?(^BKHIwcS!tW)VR5iECzf_)$ThJ@m>n=BMhXG0LW>r85BT)5PUaJF5PaQ z0mQTio5QcM2j$WKj^Q|t5WP+oJmVW31wcd}aT$@S*T4>LKG4(-y&=$M8nil)TOYs! zGNr$U2}#hy@`!-`1?(#!Y7i`vz`z$QVdxp*TO^bLYOd%M={tCT^Ml_6;jPI%Nm=I*J^`J^2WxbhwPQBWQ z2BM4vj5q2$$*|PXD*k742q(etgJk;kwcJ0GmOZR+nh?2zynkd3(d|%h7-S+(eld%= z85G%4vHv+cVWP}|YERJ%mHG0YrWDthO|oV(UGfXf4h<}cY&`Br>aIit(O&$hM2Yy4_>_d+h;bdsir=Ydaf0Ko zz1_LpjNPSOcU7tiq6$(=fF+Y9;|cU4b)}qow;~0qMg-PiPP{N>F^hb)qOPJ(t^Lok zx|RCipC@|E^3*52Ud==JK&(B=6)?-=*^OM+a`R3?39P3#5g zZ^GZW-Cw$~d^tW4-qGL1UirZXz$?M?!S7)jU^~7Hz)-=oK^Mc|BX^KJDuikM5~oo9 z9y+a&SJGEnn_t_0N%qI6&o$UgL|DX1WLtzvxH`fMbq|ddpW z+-cpir#-&C;}zzW!xi6^IkW*ZcertQ0rDF%Y`jCfZoGRuZ9ILUxZ<-SPT{@8ourIZ zqy)E=Z89I_n{tSVs2-W(zTY@}8m9)Q2EmGT-C13N!>hx+1C|5%UiO&MuFM|FuH`NP z)fU<2;QLhAl2ZDWNCagvQC-ikw25{iU6l35XO!pR7Aj}GN=0VsW=0o} zr=Rny3h}DF#XW^XrG_=kGGuEeetl_8ZjFJ>*a z9WNa38$TW=8%G;27|$5z*DBRwpwXn=r-7$srmayosI;nbQNPnts_LwyuF_i-Ulm@? zY)ETb__<;1If!6(@V$BI{AXvFcd2*aTSH*BP_a-BaYaF>QPB<#xd?fPQVR3&>6Z5K z>$=Dg>12^Nt-57*lhYZj8s`$&60D6IyIM0EoW@FTS-HjD zP2zC?Vh5fShm1IiSdzGyNQQWfh<}#$DCw47!9^joU_XCJG$%|q{3_f$oOB3c*kwpz zCx7ReEy6~6?U7KIvWw7%rI*3Lw~wViP9Y_X1cJBe2eH-g z8PQ#SUH)KJ9=Gkq?6OLiWs#eZ{fEuQM(F+4!@wEVre#}mS5Q4kfpO)0YlC&pV;9~_ z*BRofZ-sRG=_PR1e;2f1Pj(LvZ5GXw3Z0smnm|QExe*tYPu|GIk|TDO3aj z1Ml5E$j5lM^lYXHdnLWj=+TIBcyqyHX_KScwP0+j zaV?KECr{&-@1c6bfwG~Kn{)-$i?HPwvQAP?YC5~EEicGNitj~9V^}F>H3NE2%P2F< zi#YQyr{xz5q24y$Z%eo}8yz-|Z^!UAI4QQ+zfZeN+$wIG-p}s2+gw-AkJqg`OB`z& z^_siSx;EdUfr0+jke2w`*erObSasNK@6+#pvc%|O@Zmh+V|WnUc({<+n4U=XM^Z{C z#MedM(Xa%IUtEJ2)5+JSH;u=_O%MX1QYj^dxyYD#`QXo0bl&{uatc zEzmCw1t9+l*un<*4cuE!HI@TYenHLqV}iP-Z0o~oUnK?j1Vua&-BCmg`sMM6iRM13Q|r?3|r zm49xbY1WQ@4a$#HjD*RsC|%{e1D7GL5k?^S!;Zot=}DgM*8U?n(Y0 z{%PM%+gR6H?g`ETvUw6|a&7xSbucxOuMYn2oX5_${i!&$YT4`Rc-_=rv%X2O$RUeA zXRaqW5IP&B3$-afD-P|*&}KB7L6{wx)c1Bde{CkAcZjs-Q+wZClmahWBWkXp+@;l~ z>N{syS?JL6om%OXDl&XYystNFPr5o)v|W`wQu(rcU?d{>}D|$1GzYu z^{bTr`|_H)^R=6jl;c5J1#Msne^wF)hObYqOdfA>K}UVn$$N14`JPlq3Tw67L*lLM z{fbUSo6p72Nyc3Bm8L%=oTn7R3)}4T@yi*tp%ZJ_ROy{4mn0C>&9BrS~o735w zWDHNep^iFCG|Vh_-pgXg%6IF9$81+E@>z1Dl7QdbzSGa*Z;yZG?xq?)P^HDZ?bBx7 zsh(sE*e+j+2##-Fe7ZDI)vtA`bu6p~@1-8b_@zf>rx!+aN>ZoP zpqEMXhpbi2LLh|3k~W1%ujEqTDuXFBqNBVi-M`I0B)K>sxs)vwA^%3k6?amV9i9sw zCyHtb70Z?>oJq%Q-_XV&&#cUX)SC8tzd>ZPPHjdLfh(qc$BEO(Q-jpRs^XGYv#@J= zXhlhQN<4cv;^aZ(g=2Td`@td}0tKA3HUXwFUZwO-{u`7#(khB7PM5ckQ;=gJc2>eW z>#>59mbAN-N9Kj-hMUE!a-WH)xuJTzEEAnO$DW&oL%K7U>$CdMiVSCl4pT7mZ!>3; zi_!2==c)Pt+J3tV8~(oZmTWpBr{gtRCOjxNB7J*Q%9M< zSD$mUW)0RQF3MZ%N<8=CC-+jR8+oT{9PZO}3iRmPX54P}tID_&+ch6vUvAFX;d$@} z5Y74FJQDe}Us`N;H=d80n>zC3O5 z&*>?4m5(bPh~FGeAx2^(A9dfzfp`gEE&G4B1FVZ)hSAnxU! z-s*=^?xWpyLC1*4G|zsGZ47kCtP1E1GGaG_Zj3+SaK)LD*-Y`e0a5;j_7%q<{g>$s zsA0)~Cn>&Uw3K&zc3fIWMKRKoZtzZoR^n^Yg7TN7Zws1@%FdAR_CGi$e5$z4Xz=KD zOn8-Tg}YY>r>57$XTFn2^saV^wO<7N^oz)_`Ogocs zM{_lDVYGqu#ep0=4^)lt4)^yf4c)Xa$y`Y0eAgr9ulvpXk#NEUath)O`n#GRB@ypb ze5c??a3;(IR6Xu;`)(F}yH@XoavRP0C#&SYmty7l^ z!34ZIk;MF!tSMI=TATGwTe#8qEWPsZtm< zc6Y*ex@RbD$xfXg#iv!{Yls(An`0*gIF~*QJgCohE^aSjTM7GSrcWCZoS!srCjTN}OA^>K2gn6M1GHiy z#sZ$YZ$c>;LLGabQ)EsPj3!2`JFdqsilwAXWMpG+!grCm*F*qD^JdayYL!v2#=s7%{F><1=_T%W zj9!Xx4YDQXkLy%!bBodXs7s4gg7cZhCQaR zw>kDeIZv@q8BEPxhFMx(URIXz-OYUHyS2ZNPsMrcrYk6tkXAt=EBsK6H2ApJI5mx~ z#)uaAnszfvLyX<>g=Ffgn`hUs`Bd{}03UwWppWa40?0bZ*kTM= z{ak~fl~8A2Utc|YW>jjSrSP68;^1h1@&n7a7=`3V;uZ2D$~z@4y^v?J$O)gc6^$%T zn$|e?him8NMJuD<*(w|g#$C+5YL-`r_)VR3q$LmL7u_yBMX$O=ItzCe%|iUq>y@p_ zo=xWh-lD{v<{OkZb3A6cIhHmPHhRC0d<|{}@5gRBA-sPsxvp2X=y*04ea!X*_J)fM z3=he<@V?y7`ZhR6@yKQzddR&}JYc;ly@@y#zh+!ot!bZjOim3BHtppuTnS-kx03iV zx#?a)d?hLmBaio=@5y?{PzE##6wJIGqTPb7*K75y6k=z0(C8=C0+$V~5M9tq!V3P3 z+9O^XchLG!cg6UTb9`|@5e=Ii5Z-1*H%L}aHi!ovL8S@HlFHRS*KHQ4E4HoNuB)~{F1E{7+4#@|I=4msb9C;}{1f%Gx zsor(+#T=TIV;hp;B=)PUYP74o@&xk@YvVKO8b`5JcvM|$U}??HoVo1Vz&)Iw zAK;UJG%Q)M@R=|fnd)cTG8&VbWm(^hPyXs!H5eILXr14?Uln0jd0>bU%9b;T2K9=0 z?$j$msU@|e5GUh^Tg0owHO0+t%_ENwKF4$B@t|9zJYOCf1mhPKix;@wPb@J%KFVOC zvw2Q4Pfg0$$e~V4=`#6V;qmRNX)2hG8#@x+B@NAXbED0yX`sBplwS&Kr$;}MJx2};^_e#<;xTn)UH>*|6Yk}OR?M<$*dRCpMbAk6w z_cJxHzYn{U9K~MFU*3&CParr$>G)y1;Y7=`v3WeN4A-b9X4Gt5x>&J4IPAZV?!BE3 zpXKa-{LI;W-W!+xSQ@dV{{3{&;Nv!F`@Yh0=_BFm{$cTsww0#H_8lOkkEP(ZGW9Jz z76~=RqTuVHuA2*UU|gS@5zL?PHML3*HcTylyuP11nRX&A+-@+NczXW6Lh@gYk~ z!dnNHXqsruBxVb#nCRX4sp&0AMWPgkizgQ+&IjIMs@a!0GfF4t>9x_;Ro9t$hTS@! zetGe}Vu7@Q{08R^t_waBdDO3_k2u3H>p=@^O3YFliP*ZyXen)A}&f9B~V6R zC_NsRn&RpNSacTHODc75L^XMqYx1(MD}o zajm}dG}OMlG;iy&ktQG-YjY_ru9B+g<``sXtdnTvBvh%XZPsDkCvIrP#8*T%!Sl9I z+#v0xYLDP*Gl)L&x(`xd{Qx5r8Jk5O3Hq5|sU}67ujz?$#A@;>9OIsZQK#?h2>U?*ioY{tywb3%8eJAX}JTf3i>y{jIwIf_(CS*bR@@8~|BTXNO8 z8Jf|WUwd-hKOem9#)I;@H2!t)XUAY_xHu3+o8RabX&#xpcVGt?fVWsm>;RxQ*RP)?#BKmUk(0@(jwz1a?(Od#p`9f)B*BiqlG{wr8c*T_3>y80W9ZdXyGB6-D1iFr7o($s z6QiTEj4dN>2t7%udLIW2NogM_cpXE+OUy$Ksofv$Z-_gL{jvlr+|i%?1!y~Q4MzX~ z7Uk~+1f*wTezqPK%$3!h)Mcc(jBKsx42*3JP3YXL?LMIa03J84&s%E~Cj&w^YbzT^ zE;nAHe-K=s_kV}!i3tCJI9c)%smsU{3fVfC5VF#-&@mA4!4MJ>@;Dfqaw!Un{ull8 z7cbFwCnq~Ddiu{62AwN2ovnizJtHS4Cp`lbJrfh{Cj_mdyN#298?B8a@qdW?4;^6> zMBwsSCXbo`{x$H?;!^8YpVf9ClQy!>}tC)-agIG7tr*f^Oud?Gs;{N;|1 z>A%?j{}BIQT5=BNCZAIO!~UPS|L?K?!t>Do75x8F#DBE>Z}d~md@wxp|GQ*-Fq}?J z765<%KtlMNvK#QU6EYER$^Jlxej>x~8zFKpoFZYLz5rPKsA@yqV9+?BRC4FZ)Qk81 zIlfl1FxB!&ZO&4ix79^8$(kVubUY!Yxygv-DvT;RG>9++bO1CV5ZRpJYVYmsi?$W*K?zR^ehPM_RODDLF5Z`(=7&{{qDh3fv-JC741~aY{Qym|Zy!GTu1FEoBPA zp72~(>8Bn26Je7Uwo&UgmQvxEG7?UxB4v@D=AC1{8B%lI|L_=H&_jX9c`odc`WJDU zDsS*QprClmnJ9OsqxdWlBr&*q7-W+IHN?F~UiZe|$Goz6MV=?e=D)KV!W1HJh9AZ6 zXM=zkAkCZsel$j>;G^q zn*~x9{!C!TdL7s?rY}xQD zq?|~G5?t|9TO3&6n(DtsA_|`q&Ir(6x(V$#vu58MLmMhwu$Bo9tbkDy{ zsAq$?`t~SPA1qib#Y8liu&tckrMc$Iz%C2n_89(4&rRj87AoQ?XfGpB!_I+JiGB)} z?m25?fQVLH{UxFq=wG|WbPc1Rk(uR7%q^5)PIJ!Zf%sKgnp85t>R`+xn}6#r{de8d zl+Aln6mr4c1Lj$&qDES^12VW1%t#g#IHV9hU^(|+%N@koD`K-Mh@V(3=o%#)66RF_ z&lY~>XC!fI9q01YzH^C+gnw16R?>4gFj|o!BlRgUILu+(tgG@i1>HhXyi*bqp``)3 zTxc3xk7@!>C{UWr7EQuMAa8O3$gSfY6?@=ZdVZ=3$O;ro1#at)=ILn~q2w$lJdK3&ZkBUlj`3;cy27^5@jgt!K^WU^WW#^Xu#p z9%`vzP8~i|T>Q)^{%aVDFquIhWs)}}K@#6|%xrQU$gsV~JdmoSkhsfZ1Y2E}%)PckuMQgR%y*gpuqi3vOKg|1hpCiJfHO4IR7q{uCgM`-^p~i$l zsB7A#@=Sz1^23!0CWl$Xqvcl;=8bP6mng10Dj&B@$zPT&LXnSu&C}jU#pHx3Y2Q_ZK%bFWA|B7uG;`IsZ_({e zwzy+hsn7h+R9}DR3&6O2G*kG7G*J6glR*3iL+TY}Y9_O@|6;HftBJxewzNv4N2^Jv zC9qWhG4b2nN6tAa(JOn8f2X<$d21AeY&9r5HJeXbrwxP8IE!FNB z`C7{b0Z?Kk6{C5i=!onu19M`39S(u@u(NWGTU$`IB8 zNuc&1({;~q{o;m>WXKkFL{T;2iRC~d9oRM89sAlN!l9_I$18BM_mU2Yh~ZT^{O9Sr zR&AfwtGIQmK-d*rQWM;;&zu8dxHUPT6_UPdzEi0qm;OaWKyXXieXmt{sH>8>-p>HR zuOexs#7dNFxExN&$pD07g00U=w^Gr@Yvy}UA8rFk)Pa2Dc5~^O-FgrXzp9J@)CAeK z?D}&sl7JZLfc)Cn$B-LiIp-~NQ>t)`{lUxh`B;stc^Ox}@N|VUkhMA4~|- z+A!5&y(JI`HNK%xW*9sahK2*GDmYMq#9Hqkwg}jRX$2W(wd{|{b8>q&CZ2!#CVvHDxPnNZUa(hS?gld92gEWqRG-h-HFIwMul9*yYILq|bP2TjVzvc1rmGPP zOioO;31rJ%fm=df&t7hgNl;A$bNWOmmqoUV);H^W09 z=5{JGW|25Vy%qQB2wnSjv0meQpD>E>gkH-p{I!meZ-VbmoZ3jM<$-LCt7gI1ezYBx zOXu2-&3G%a^Jo%AOg?dwN~Q^`<%~o>mwy2@G4D_P!W#}uv#7q1@Ls5$*3K73ONW;y zM1YwxvPOP2VC%qNy&j64C`DZW>qsu44!zKkAtZhPjp8I}l+kV&NT%1b(R&=H z^;1oAY#~x^X`5Wv(V?2CoM^Quy6bw%y5FgaK`AoHl#=Qnzd^HCwUw{_G3=`UpvwIi zb3&uWxot6n3`hm%uoU+}(hgWK?U9&L;*pbMy=dw`Go@edWXH_2?r-zZb;6xe6$b_R3I143cLu+$^8eaEg z>eicUmBObJR6mT<)~M^hTQxBmFF53&6&(+h$lbWRt7`Q0*Ff_igBe9^Shvih$&-~b zQzFR?_0a)gBGofu7H}+Xe+P5qs1<(c5mgn}t|OgmKyA>0d$p_;kyGGJT zWHK(*{BQ49{d9b;nj_p0R2cFU(EJTks_l#mmqjQ7&;u}#bOFmOeL6u{1M>SVAFG5v-UE<rOPUp`ScPw^|ZpLU*O$B*wS!2wKu z%o_g6^07ql_iAFLIXv3f*!|yjVF>$2J>y@ah0uFt4(%VM&Y+JEHMRdFNLkpJggcGg z&DLq!cgXmzEx6pTscQHRqh9Z>mGp4}vK+>DoEOC^6Ius!K5ldIp7sN!Y4P`YFm6zw zDySVApeP#%V*V2~f12kf_deJ;E40F0@E81KBDo4=FRaRLj1^U>^(xe=%Q~(bXmsBK zMgi*10@A@=Z)$2!_HFfZ5D=kp+kkeWcyxhOvFD0pdp&)vsRqY&AR&}L z$avXUTIZ5-1PeKxyc|DTKx{PjNEnGUL{9-~uBKUdfvEoz7kWumw7z=3vlBRU{dcr7 zt2C)w%-r#%ADXTq=*qTW+(1h(wJF(;{|VJ3-Ab|s%v?bG(5^fssK}+&>wo2vLdLTS zAf8QKq}g)2oI8r&7nL$0o7Q7ObOWNye-XCFQ~-J_Rym=K{=Ab5D!AX~T*tBBC|6w3+86 ze{;)nRB_;iGG$V-Cl>gC-{7>?w{2l*EG$HZ1p4e$mwwf1U6bbDK4$e@R2Jfc{Z8@# zSV2KWbMBeYb5AOY`#zHWD9cs z4h|5!I7C+OB&y->iGQVhJUMIokTRV*GtLWvxnsa7nVgBnsVxOnER)=|IxomC;Xe&bydOLXspIYo94e2)o~;Rl|7?@!V^vy*(nK;o=CJ57b;~Nibj#4 zJm;<#vKNTpIUCtHxc?{Y_*@|1MPZ?YTqX>7y4Uk#-w3oTSLl^gXNmWlhlhvN!DQA1 zb*2gIr8okQK?-PJ>;j~MDH>s zh8x*|xiA#UqeUu^bUtrESuF9Wi)WFNi1$oXDX2jEWygWGr+@9%Op1h1FgetlQ)4i9 zMV-i`+6+ed2=8&*t~dXePSTfrhPw1666rUNg?<&lv=^9nH`eykx-qMh#VS?06uj4C zx~CsZ57=JoKd2SB*%;1htlqlL;+&FCn)awwSJPQ7<;_4?tU26`-ZXlAZM{Ffd7ec< zvw2>foSt~*G|jHuRO!(jrK?qpfFxdzSB)@sr1nmez&=6`KxzMACJ=xigx-1t?^&?? z3bw62>6-3Vn4_UwR>vk16Acc*Zha<4E?eU!X7eD{q z0=RESC9PJ|_+qur$&G=9Sd{ko?^gGGLFHt>T(Yv$*5R|mdbw53PN~YXR(Q5YIdzxg zvO7Ty>YeX=;%^^-Lv60a#-r}r3oElmJOOw@6LrM^apjOfQabql@#m2~#glV);_~5_ zp2Y+|;o~I$MVC_?oB~HRs50kjd=NQ-LvNH{wQBDQ?~-T|IQ0(p%ppOpO(EZWS(ioo zJ_;pD^%fOY*Du$LQW6vcI-T}+ttP80?}-!6WoY;HZUjH^{J2NBlvH=<9porgGUaHdhasOcsIA_b z%_+_^Bg!()2GP(ng7K9bu?iPd9AwUFW|a_BaJ%nCcW|;h1Nt*w=`}_G`8K!WrV*4L z@Yp%(yby2>bwj3MNX>f05XKJ-rHPww4arGsV;{nz@?}$*L zdLl;;k!x`LI^v@yy8;o!diu!mq?;4vmk-U>*zN|ENfbQ--v||i1g1+j2z}~avZ`+5> zr{-Kxz-|ikZp*s&RsfjlM3V;R(q!f;haa?F2hw~RI1H=XIFMYzv`t(=vqOVlnN-rE znH78*_KJ}-OQp*3F-!(~*~nTvirCK;t*kC90%o2T+NCh6k@AYqdLOsmmA0`-k-#mO z1+s7t%hBJ?JSz!l?V&Ria14`M;~@dUa1rv^U>A>^{yoi}G~*7hOKH=u@cb`}Q~PUX zHL?W_1Kj~2@yFXdn?Kk$509l0aUl9#w-SC8ayEe331&*Ma*VEzVfxc(*Y@ze9m%~o zVXJt!Yxq)4JK^=C@$@NBnpT44DzC+*^&qGGqEG~VWsy7BFJwspFO}}{tsEmK!~w@? zCMTt@&h+z#1C}m)cX&M?j}#2>H6Bbdyyt9}d$XH0_qW~I zeD*CXOIxM#d%_^F;4~vD-|ZHE`K&cRxYwJpYg9WyZOttw&6@%k-{5D9bHv|+9I0?} zIbV~EI*d##XPo%|CWCiOQCHbn6X#0zJo{vwsrvKexTj zR+c3n`3|}G9MM-*`IpyOXWk(>-V8?9pA~JRa*w;{`9$EIrkcKGm2!qJ=QA*{K4CYJ zkPA8B9)9^g>lDLLZDskCtn{Cf8+qR6;*o!qPJg?}6JXIyMeDr(KCj=D(Uhjwudz`#{xc5&o?ie3tx^u;I^>tUQdKJnc&_=R{AKCy z`{AawZTA!;`;dC^Xz)9YWDX|v88Ezp8Flai_*QbLa_?}G1qi~E5-3{SkqBnNT$aZC zNOClpd+;I6FbR$4BFew3q*NkMKFi~*Sw!j!0TZ?&McQJqKoyf!W&}(l;rCCtNAn-V z;*!>p6uG)j2arf~wlJ*+a4FI7UA{#np}1TOJK$`MPm8aRjUjaqp^-1C?Lkk*f76rz zvWF4zd8=hIk09XFYCIJ2F6KaPsb~4?XA;6MW&+|XxJZExqYwzW9$uNILenS9GQcF| za7hK^e%dTMQ{1GMWc56-2QZ}Yr*KW?m~MU0o*(5pbL)mUXEUAp3-q#5^Z~(|*1pQDwoDfV3 z;8W-siJwA2<^HC2rD3$y`Fd-UcZmSxVszpDIKFfwvzkpUg%QH*$#rG%G(t-gl5f2X z095hU^-l!9y)>Z{Q|SCI0$z)Q&!fMqFDYyF#GEwLMU`L@VX^VwB*#&FnPU+3Z60%Z zA9g~mzF+WR_df=;3O2%XMJtm0OkS@$V{CWwiLv(Bu66$Nq88g5)uXJa+hoOBwJVP^ zB!if`xQ9)!b?R5l&vKDU8!6`vc+4!oR{B^8(TVow^vCa>#<+K;`&XRGL3$Hl5A8g-&9CIdWbedK;i#4v4mSAF6$Ud%ns|wt1cI{c-PiXf$ z7`nBqgRmOn$#-{l;daCJ^GTXYHC1fJJKPPT1b%}Zx+u!?$*wZqNs~wbL*m-%5s$>T zIw@OJ2l+EpdZr+(wSCYNaBo_b-Y%* zUT(=lTPs2KIyDz?FJ$75YX5weK>P~b$@$;Vx7zJU? zT|;{UlREFddLoUDoU?E0zpRoeqCpUPQA9R`!xQ!;}Tevs?#EqPSIfrNK3r<%nu(s6&9AqhZ zlQ1QbmORx-RX(n$#4Kwx%2ETeB_v60IXlFrQ z_KXJ-WP?y2oE}$HH@=*A4)=zXu_2Z!N+|olBd&>nYwPw8bpHTxp8lpncba9J^9JT) zbNZ5AhxyBxLP<>+T~ZlXRSiPA*DdD#ya2@1sewUD)EpvH1*=+L$q+@}GD3_Mf-$C+ zU@*6Ex-t@!v(EcY5#zf;-XId(wl>0w6PxR4gQZjCYC-giGwmhsl-P%q_a zZ{33^mn)|AbR6rv08x1{Qe`UlC%~Uk26PLw&l{I1^$)*T-85Wh80V;r(%-1EM)q?J zb+bgxoS-o@y@Cw${nIR|_puen)$pShM6f5L&@m_Gz!~`|$xp`DY`Zs#=(7^bWg)1m zXN~pTP~L+q8IA1kbs)h=uzc?4nmOeaUbB6HUG1I71F8ocV(4}E?Hf#APjo*iojgw4YFgiOS6SZgC1<$jIbYr{Fep=k zJnHz_F7-&=v+Qub-rB4Ze`&mJ|5MR3jPB7>wl5bYpZbnhayH>Fu9p( zm9F)}hHuRjOdAfaJqt4c_i`sbQDtq~Lbmn~)6y6ve(o*n8H?93-R0Py$!W4?AVDcz zlti#{!s0e;gAp%;r`L;7(`6lgA=5rGwYpPu#{kbpq!r@I!~1#7SyoM&ftt<@`kMDz zPJNW#f+So^0Lt@Ml3t&EXheOE`fi4m=ZLv5`w6cCh;i*4oPI#pwQf(l;8l&-4<~if zzJ=U$l-t5C(g%u7^1a~~v}WBVQhxlB&w8hkABcz4EXxq3-Ko$Q%u+wmaYeR3#*r6k z!X3($Hj%svk`Wm|es*O=8CwgvG=iN-^3!;H8)m_zm&vuNwhhQV(vE>hHmV&>B73_+fPI9Hs|P39WO zSash56hQ^S^BYjp%rX|!9$M0D+-4W8f4JXZf=$U@j@>RT^kCD>QO;mAQhXfg!a?Cu*s*%8#s|0l_wBT=;j4^p6|KT(sYNYyZuK1YTX$T^AwMU*(i~K2bW9N|wIX%G zqOV*MzJ-yr?_x9QG*b2?q%&hTK!IVzxzrD@0CW1~gjB^C7Kchb`YcK~tX;Tk@&u=9 zTvaZt#AhgLxpWb&m&;A^#6z}Wy#X5k5&rbq1n)_c`}8uCuby7BND;rob+~>(Mo?{d})fF|X=ary6f}9)MeI^K zM$DP`Z|;B^Zf;}d*!<@lx7FgPliC$q-)=mMj6=er_wRJmDYyZ2a|${(n;|v7=R(7g z+E&o-=o;`cT!L&4gxRB<}VT3bemN z3dMrZ+4&bRJ9a>71y*Qg4bUhR0gHs_CFh~vHwuNm^R`m$Le?rt6y^4~+~CjbKEifN zKa+ndN8+z?#$P-}3%Dq|=b#w}z@P?|iN{c1;FALkKTo>tir1D%p{@wej*UyvIhZ-> zU|`aj02}4QsmLUF<{Ed!j%1G~(Wq5fFv9OFJ1)aNN+A&Yq89f1M5IocbJ_-rlnuhz zX_^BIIX_=iu)$sFnu(r|ba`JFDHUY)TYws8ktQE$-%4*d1xYhU zH$5kk4|k4?_B|{})7ZVBi|K&nDXd2S=d`)XxHRZ8G(sa^j_EDP#*SHN2>Di2vvi{c zKj6Mtyu*su zJFdg^*KFOjsKmW{e7~qEa55S2VcS*Z8*xoyxwG214bRh|=I)urb??w5c1j}Hng9|3 zG{cXzcGuN4z6HxYXzQ)GT>LUA`(8lDwEHOqX}HAT;Zkj$%1Cp*A}`0sH(Wp@4e-IW zR`u*@{pE~;k+=Q{V2bY}ZG%Pwl>td;DMG`uSKcF1#MI>%By~eUm);&Y8;@XexHH5> zXl>UBC4jD+(ndeh2@Qo&OmBs&6-565KVE?KL>^>io4*6^+(P-G=McU1hvEY1--q&41GsA*L=iK zAFXWxH-9I2B4)*e#=bDx86LN8gc#DA=VaUYM~A+W7PkayQ#ed7>1g1<+yN53nAr-y|Ij3GlS`l$Dh?+frwZl z=}S%h+3mV=p(GD2MSqY0Ko*>8Vna7}a{#O5BFCf1m)ivLCt^FKy1VflOD+D1YoS+1 z0Wz(S+;dC1nM7}lZ4#0z+un{y>!oA@P*WjYq5dW0d|W}CZLB>zgvy5x6=WphKC2AnzHnyh^7Fi5=Hp=LU63wT-mn~YhP=nYPU!o>BssUp3B^~ zmnp9yHro{o9M{hR=H>%mMduw}viFjwdWH)a8o4N+xUa~nO%2>~w5{&~g7?8#STbgN zso}!L>rQAQ9E|*h?JtWb96!xR@?7c92=Axpr*j!v#k0k;?PEzQ(qR;2oKD5NF{V(k z|6oT$7BU$^h^EvCIMk?a+Nr5nff4s$r|q6x-0WOD7%Uf*LQ_@L!1A{91_(}BOS&rb ztpyYn#V3Dp*g=>G%sW<&fS_B&ScG!&q|30*aODYE4;O0ZlHsOlAhag3D_ZzMB0&V+ z+QmHY_!i1<-0Xd1>)kd^Dwj1EJ=I?JRXI)Fm<h8j^ESHVJG-D-Uv|;2 zIhx7Uu0HYJEBXYeKOxB|>-4q}Wp)qy_p5YP}hqWD~h09Y?sigEmFj zUGM1c++U*SymOoCHWOyy$$}xpRBcL9%@uNSxZr zCy;h>avcC*6b&VhinA_*64ZzV+L$nM#Kx5YFs-JLoycaY{mZVGY|7#{TcbD$HRN>i zCb2XSs!`}uXFLL78$Qfpv`6iszxyj&`M$T&F*xsBHpd#wi^D*SuxU{TOLlL(JQCO@YXP&gem=gF6WYBC`V_B#ZbDt|+NV0*Zi7An5GU^_PKVW+ic< z#;ai&DXUBwUQ}35PDN(Tn`;}lJ&xpu$-T~z!d2P}b;V{SQ3=G9q}G&m<{fw3;cCGM zY!Tda9LxFz{1HPJ!@qpV6}D*;K&h(uk?nnHxafu%KHHkWQw;-N3ue!;=U8J;>%2N3 z(03G<^p+6|rDX|;1G;)EHwr~!DRYz|@H8lFU6rHu=1F;b@7(h(J8Pch-n-he@BWZI zbg09+-*=PQ2R>}}?$uU!&-G>(E#yO?%hqq-jT&=~i(OR=XYRc3PP_cd%dw})vugU| z_S(zXhh|z`sG-%@Whhgj&lu8V75zmzVJ92|q??i;Wm($654S?udUBo}q-meyLnW(w z1I+RZuemM{_f&<+Ykq*}I87-9&U^|4j&$aaGacc{DBw&~CxsTHn{XgN2?izd{R;Xq zq(H@q%ph&ZN>OuD(wjM!)$9Ym{2TV)*WAU5;TT@P*c+@KAjT|4tE5)E$)q{QQ8EN( z3N*cK+cqz!Ka%|Pi)zdWdfF=Kn%;T6_UI!UI1mF5`N>IV=q}-rujXV-Q)e94uVA^N zHESF!HOp3~4b539X&5z)6~mNv{Ol$nab+-aX-C?tAkncb9}CGIw)4l2v%TB*+6S)x zkZs*}7>mlR9i~jSvtUza5N3=4Pp=Q#3#cOxKD)~v1&}4dKE5@KPyJfIalMbPXF;$1 z-MVksb=NMlf2@wfdjb;_0$0o3LQ!k-h|)f0B)5dn>NQ3&a$W}z)n~e_m$}ZGdvzJo zBp)dHV3EA1BvYE^?dG_7FZ^u!C#ArdPXWCvX&S>65YrR$98K)Ea6+v>UgalVo0CdY zs!hdv?8btygI^oJu5$r6tOz;YH|{)pzVjT^f>ZdR>dU(9;Z;Vq8)PuG8KgD=+Wh(R z-ES{SbOJMhozn4=o$@rlC#Jq~*=oCc%{rg!lJA>_k|95bB$pLfddo;iNNROSOI*8n z@j`nHXK+^SA;vR*@`{ThQx{6Bzg(-Bm`{HDK6~k*zqPBU58A=6{Fx0t^gr#u*Z;~U zzxarK^Zx%qD6+B*b+p-`B5KF(Y1ZE{-Sz=k1C0G>b^<9-f0aY!3=A$Sb5F^dTkWS%DLPnRXQ%?Aok@GD8MWMc9mQ^#x+Hb z74H;sdz2f9;E`cymONQ;3izCwx(VS%gkuiVlu}@$;O!8pbD#3YsEHV_$M zlM@OHP+cknmez=qU55ayefE4?xcoP)G=7GIl7LBWVikPP9v!ONf@L4I>Q#Wqv)gU^ z7e5QoU{&ZTfLwBrWWl<*UW>%ud+)t2$wVjgxQzxY@j3xunBU8K2(p_${VDn(!xYs| za-a*$UJ{ZEgaD4ZKYzh|`w8(qUE-wAzT-&2Sqe7XD1@_>e%t?@ui3N(ORRg(2CIB$ z9RMkpgogd-TN!)%HA}6(?}%+FKW&5EGZ{bO$tp-=9UWFe+{zJ`a}aCF5@0BrWwH3I zK_AT#YAz2vb9%2`bGLnfkYnc(eENZV?yw1{M$45p9MK764S?gBhlQu4YD75A)iI|> zfKK*DzepB<=;oOE>R=tLHIB}@&tLJj%X0>Ge@aPQ`AV)7@|N5cw^{h zpJ=Gb$3CYbScFpImy(a9GEmHLPD4Q zWW&QD?3ah~qLBBSwg8JVz$1+C25B@)%*v(9kqGb68hfmr&it9?_J~%A0gfj0aDWFG zUHp>29RT&~*S_EG`qCFz`QS(xfTUdT`dywpbxb!El=_yNKjnR{xt|=y9n5*@HVD*Zk?OvD0GL4fN{n!R zZ_@_vQ(ZtMUk8ne)zF_LQ1m&!K>6_g*k|2xJfAt+&Rh8rd-{ui zVzX!WP`ADu0wpxnCJA%L=B;+qst?)2pZY_4?8{%WYp?&X-SgWYvn8uzZO` z^}gQfuX~fVUvUKz9ODH@wW@>`51LXsWIwt2w+PyOG?Fwl;g6t{nZ83~X-X+Dwka^S z-vn{FEs453ywjKwPv1?IP zz$q(9Pof+mgnYqryv?K!{PE(%k2*Q_O$GQgB(EMb98^e0>MlE7sbBZY`>P(y29>sS zPD$!a|AoW!Z%To&KmonIV>=}b^29_CdBl)Zh~#39m?Kf`9R$O?kywrRNK%Ta6Rhmq zqD~Tvn65tMljL^r@qle?KVIB&O1sXVUZu=&m;6+R>Yam7Ya3#OYSTaXeRAaPS%-^@7U?|%>e}Zo{(x# z>P*GrRR6TRjsP>zx^8pl&$Gw21fM;xFZRD#dDsb3Aq_DBx$L^7cK`kNb0UmMTg{DW z)dD5mMFo78WT@ZL>z3QS>+WOh0HBMV)FY76zEr*3XaCf}k~Jr=Mg^+C*@~=k?zp0z z!)gnfyBjVL60H3!``XSuHsi{7;iGpBbi_}uV=BNm&Ngh^#PULnr95EQUHv}PrMKHh zm%i7!N(XHs#xrkQel;!>%;upU)|{Z$&a1G9?MS8@!x((^8d$#Iye>nQDqWP&?L*|A ziNromGIU<_PE$&Ou}T5n+%cT|3m5L-L4lz|3o~f)Pyf0XgAB$7`XRAODA0)mn#CEd-zNj#R1Ds5kx0dVx2 zF3EFf$U2bbx{(s|Sh5z8?sTpVOO(pd!`9A{KRH=u7Q3zOlKJ*{eu_2byuq?_-)Qxj zS6IiaC6KRSJGQfUEWxGgxEK7zx`*ryAO0P?`)fb6DGT3XM~Sj>+XG***_SQigNi_D za(>rsU_}bQUuYVJhq)JQWf|&UURn{Cen`_0lWu|kni=d+CQT^?#u5d1Gsb#?BYPTU z4t}UFV7|HoGZX}f>7pVM1BW?QHCZAi$$y{c5_i`=h7mc$kSdI^R_z~~)XN|Xg#5b9`be(PRNvjv9A;Y^W*Ulluy$fj z4)z0RMQ6s<5rx|dfY|0VWMo-@?0i-W=m7N8q&P3uhnk2Rp8aNfrt*;4%-4Zy1af`~ zX|LMnlAP$H)+O^b9Q2?Qm(HI%#~%3!b8$}7mybd1$E16vq$n=;-FIKiPVOtfngE?# z8nmy)Vg+~#Vl6ibrD&<@ZVzfxK(BkZ_i3A)>9dPwFSIB2zi7|*vC;w(mjLqo3oo_< zgN&!W%d*`$8|*(yKGGK|+j@ny^E$^{bpX2I#-O?e1(vfH+4k|Tv6+kBYU8`+*z@Nt zw5L1Ut#bB7whwoYA+;-2uW0RR*aq5VoZ_{TJK$Cu*1RNRN=TxixiHPP`GENY?4K26 zY7r&TH%%!8#s&paz;h1VaMvqAtj2J|I&crjA%%4ThBD?jDnpK9hs}KZb=Cne z)M3=Yk)43lFz<(+?zj0L{T*u`F4+^``kM9a-oj@AlA;@xFer6R?L&4+*qSn2p%oQS z`MJSKv)`{w0L>GA>QkTcLJ z>;2HDjC%ziNOc^+0sZZJ58FlOwcEBmFEH=cW%XM?79^nTOGhmr5)r7 zPt7lImGczO#ACJ*=$d6(&i$NrRdpD$n>NrU{ZPB=4jVtGLI6=00~mMk1v|fsAjxvr z8(|5X>^Q<}G1o^BmIm{i1ii8&eS5hOiLcUb!vs_wC``qjL5B1gxxkpk?=yH{k7ItV zm>;%2`K$q$z)6^gQXfcJr02SrIER`_n>A+vZVaD(8BlrQ6Z{c)tzW<1=N6+gdjzlu zcADeUzJ{o|zDFK;#M_dlR(L4q_>hn`eLjyP+zzHs?6j_qg1va;u=S&+%_H5Hm`6L5 zoni-H;F%~)Kn)9k>%)gfB7?PQU9Jt(S5j1$S+CUq0la5y!Q01Wx-eJ|L!t}Yu7knP_3Bm2M`7ZZ2%Hd}bjhwKpZoB0p_XCys7LimU%(0+~k zG>Lh{=fChdz7mem9#*72Ita*pmEfLAcgZbHH)DnZV;t~wpPiLEGdkw3>x)=C4#t#+ zNmVr;BIjSMI^9*pFW0$BbN1Z!umYXWmz|9tD`@hV33CNNZ8 z32+5A&M`^*j*o03OI7}8qJNxFca&n8xDB~Khrcx7j2(J}*~z3%kw@p)iuubIZ}5q2 z_QOB@eRPWpZ3WKM_uTSHm?|Fw8cjiLl)@TV85N%-T@J+DWmaD*vVu3@qP60r9xZUb z2Ccdk0U2WqwN=x4behYfoKUAOr*4UOhE&+N1%XLs4AfBD~bHtXw6n17`WKvOyK z>seJD-F1L2_t#FhKqqJ{dTAWGKT5hiX-X+DMkp}m0nd4+{wVnY+hdq03|HJs+)gnT zk?Mxpr|=a%&5oc(Dq~&QC}uHKkQqHZ9`x!!$5d*-Y>JWu<@Ot_0EKLk&&Z%%<+Ct! zK}7-+z5YvF+6ib!J4y)|^&lI3YtQro~j zd-tXIfc@y7%myXN(XcppMT25r%kh*^r%CmP#8E=>XfF_b1+}M7&=r`w!jiQDUGvbd zF+w>>A#Nn23TRMbh$5({4@iQd$MvgMx@6P5SCouErSlF%x|)4~nIt;xx1Lk^2z)Z! zkIN9Lyw1&=H?O%&QK6vdDY81H9scO!B#VU0#_7>f8L_jlMjhhWC^E0vV17=j#wu2u zWt{V?tWsVh-lbC&5R(657HgAnnL#v=gdS6+fZGrjx^g>EKYjhdVdmtJc=s_sI^kfS zP3kV#45EtddvdGwTr|U;TK|3fwVOU{|L$XdY>g{kZ^I4d`tt3l$T7Ns&K0aSwJee4 zku1x@u2m?=n8tPJ&_;9>eKjx*CQT^?#sCGzG~hWC<0gxV9rMn=j0wOT_|o=-`lyuY zun}S>_MyV6$_I;i6b1dQ!ql~2CNxx62TWV0^e}L(TAhQ@s0~$}2MlVc=%g9bvG|hs zkj{s-=U}R84hAgsXGj78mHauTShqUSl4KpJ1yemK;s}g4Loi~g;snm$19NU1CQ4nWz{A7D|$G%4G~|06T$~Tt%eP zjFOqaPDubKss|rCK#XGrvEI6MtDn~&fn6TerNV)!nYgccygB#+?tgr%edRWcVQTbe zBJ*fS`(BWFJ7ZK6f8{?~8PQmMFSG$f+A^lO)4FZSxM}u7RG9_lHXq;eBfGdT3GMJO zbjGL!f5+NL*7hIivn7jW*`DY2TKD9s_Vlh@_S)B8X|F$9&)l%R4r82s%!}52j+yZz zMURyD_|p1$H9opXiiRekS^k7t2+8e`i2LauCJDX0VEQMez!^?~F%5XSw_=fE?KS!0 zc@n6+99WP8U>M}XBNd0S3h3#l1xITmn1w5>6h3HRo_{%yh&wuF1csVb)C-sk(GlJ1 zPi|EXa>w>`djJ4H07*naQ~-p>Jye_e>gK;v!o$OXSES1HLlQcTNiB#b5ewCnn01{W zm;)e(^NV_C*^}EIbpweUu{1{%<(~^P0J$VrfsoHtQc)GtdtQw*u4|akpgrT zz>>XKqvM(%0VIwFYFi7BlB5|FXedb|7*gyHCtCX!PycJSv0HIVT_HM5SUwb46e)pd z|C)=WdEx%*RZH#GTfd0JLmy=(2>J4;{~EYusC(=JAPkMVsuWWAE|0X5jLYL+a!yX` zMJ}iha}nSdbcO{h%vy|g6z1(K1CS3v=3aAy-SHE^WzOquTw}lnp4dVg!3`p+BL!kX za-&~>MwI5F6ewv=Nyo0rM5QPr6b)SfCu`16e)5yeI+}HHZ{?#W(32IXK%)aGtblZj ze}Pcl0V;%C3-?d%D+9YW*?CLeY3E*iv8~_oq|=WcIsiWN>^`6x*_Qdcex8vU^%L-u zenVNMW~hQu(5~lsre>UF6K5^7FModn%N#AS^ZKXS0AMPZ%gV3^dK6Hv zs#_hpIb2%

GZvf>1w3Gqja)BdhpKi6UuADRAafU`zv^nB3?qpK#)M&lBeFj8LLj z6Rcq9k|+cMFb)L~E?`wxk=?$4QFA^+N149DV50mrP*hDkZfehAzMp zBl2USuIM}w{NwbBT8_P>qyvj{&DbTOi=WWRpFRa(JGKf{C%T9tzyiGwDmmrIHDS@> zUZjP(J@Leo4r<;i1FI6aSpcW5fqNuLY9#P5hw8EpjVc0lt*)Sf;yf(}YSmc~{Uipe z27)DD_RGI%hsU3X+72*6Cs!!8+4r$@%)D)h&3ntRl{bCcc0K(pjnO~oC14VWX&XUm z@#4j<&eSRlN-ohQWpylR&!udxQFyVrbLZNl8#m}q0pv(zl#NMXSOx52zJRfW>TvUB z+$aDXUr~=CWU*RpaP$0|gnK)kaA6D2n`VzZwb#{-0?HbutUuoM64s!LY(I<0_A{5M zkE9`tSF)m$fEo!lM+BC^zM>sG+^|XGCfV~x2W-~?BK*u;Y|jroZFA4M#H!tLgMmIs z(e0>1JE>pN=P;mGFXQLO9HOh1brbY_G7h7i+7QQX927^GZc_@J`4kw_fT!Cl=I-1{ zVvBZRU1HNZ@^jk4!G&#JE^spT#Xtxh29vIcF*-6)NNP!#%lL8Q?0MA!^N~c*My$!Q zeAskaPU?lT*#Yp>u1kQEX zJ&d6V#=b8X0op~kR-z9IiY*o5HPbnJ{h#(x<8~f> zp4gE4Fy_H917Eco^G`aJWk4NVSHwwspmx;yHTF8IhcmzRT>Er@6{8^9MNerN3^y78 zWSLa~ik-}t$xS2>!~4*x))bgsd+oKhX3ZKur$15J(|!c5aNoj5hMdjUt{n|mrutgz z)O8UAmo8OY&IgpkIB=WLZPc(60y^{~o=?Lmd|Y)17mY(Uj03(xqc!ly=xdu~kG*iz zM%p?ESk1G6N;u22rM2%GNO%>NSdv8DhAOhuf5fIwo@9HD9JQkeaYadO-RIZ{^<8qo zx%S-t{SMau_|^OEHRn#V5qu)sks3>MX#OpK6rN}5&LN5ChFRG5yWg2l zr4$%L6d2opCvL8vCx8a#so0ld(aM&PBD+ey*U8|>%Ogc#z@a&j8WNj=L}!_|sr!Tr z(n~2U+<9~u3q_gPBe_V`SA$^-=VW1T_-I{m%jd1H>l~y8fCPpoV}=TPs7}uxvO{s@u~#s^pc>SpP3EqNm=&!2Bned5|ltwL8ClklmqUKz$G$)jg}FJmrZ z*s&Ao2}?vx>M21FEss+#lLy%8a;?B84?D;SKF&Ulq8-MuU?Do&!X8k)hLI1^Wr!s+{R|e4Qgs$ta;U;wX}$vqNCrRt!J+<+&fRfwGYP1ajt8v> zbOJ6fBP&Ug)S5DI*+lG2Nqbc!a}mQobi$42n7J=La3o3QP{o$HUvlo&JydgAF~WhL z(KmdJz`S)5bF?f;3oSq$;~yELw&gqQC>EKAhen{dh%A*YDpTe)Yk*?|f5ve$ZP@)oyYTHFbWK8C(k_=A?XO$^k%Kn7qhx1wBC#FZWlPTMvc8S~?EZR(bKN%n z(#5vlx^0+{Ze^a+cIulSTq`X>CO3zvXxBzRx~q`yczhvrK0$ zGMPhFb&yE;d)ubKbOd$+3+7f}q!}ve!t8(QIJFD2m(`=UE#Qqk6bHa7qir#oXxuQQUIhaEGkQhB6QZZHB_WtUO=gOs9vbni;8l~ zwjF-1rl8Ep-H-KZOzM)P#2zd;r8bo{C)o~my0-$aJbkVK_`Zq+QFmre8*c}m-fokt z9Y~e^fE7||35l7~b=(p9^PNa)syh%pgQR!CSrhH-?k?Ml1?O|m@3l!6p34dg9mvVU zVZK;n;M#-zgMi}!>%H_s`-kuT(5{$siEZ2Z9b0+TRraS3dL z!vKdf>QLj9K|++xp)XD=nkfqct-j$VyVF-wK(Yb&>HrDrI#4IZHx#QvQ!)M6`IV?M z*W4v%bM83zBIo@Pz^NQfiC$c%wE&l|zTQ=(z%1ZKUsbKTL-!ToB#-nbHTUe?|i8@JRB zL8y&;`M@d=h78YiePE5$h|h_n*vNL<9<6K)1piv`3Fq0A2upPQUU#_ z%L(R0QC@PMdzItamX)qPBJ_ahnaA!mT&K%oq7JnhnulhIQIrequ{!?}i5Dc9@i5({ z6gUY5#x&sR{fsYGpbtk82zcrA?y8I=FK4R6FErF@TkpM-6EH_s{tof6bR7&?FE7mD z&%gYD{niIQ0FxQCKl!c}recRs%)CI}PI znrdn<>YK8Xl=MXoN397^X;#6hiBm#*Qf?yqan99hk}!mbVy=>Sk~GSwoQ;IsCW8ue z(10DN)C~=uB=B;h47R=UQQNlJ!B+iH`J`A_UM8wky}%P?n=tgEP41m*oAw?Alkiid ziK$a3^EhFcgX*>q)#MPqiy5ppHECLe(U$?M4kG>x5xu38_3*ZCe#YMMws+XqZu`8= z7<%4ry6Fb{ulIb#@^h|qzfhJ_U=Z@5tl|Ht&n7^RC_y!hSA5QyzDq*&d+(!Te3bJ0 z6EeNK;Ta0|*E9GdS|}a!9C(J#C=j;}be@km-E8hB&3V!XlvmJtG5fL3P$(&*I*vaV zs!9K*6gXuHz$wOV(tD=YH!x>7jgm7pFrs>rv{J_Ua}*6YueV*&1MNvTp-24i>4K32qksJSC?n~~Ifl&J6V?$xOc(K^ z8Zi_$;g9aLABzY5aKhRF-8@up$BVBwqX*?az$>B0TbS9cWI5VD8y^B0xzJeCgHwQZYA zbqWvWhDdBZLFPIi7sS%x8dRUN<`UyFhXeQ%RH6?dN$C36kZKmyG+Tk6#(d2+*Vuy( zKIn!nIu0K!Va%ai#ir&4Z3a%{+xH9-m4%q27&1N4-*4ShC)ln-dy)Jm0d(}4512OA z-_!R%mifISIREeK8?y5zcS4>C_P|e`vHZNZTfP4&d#3Fi>zel_=I{6zKwD7Y*=*+v zCdYhhCm#rXMLq-?s5xaIq-R2|9~mkZ>iK+a^5}6^8UiJ!m!9zijr?)kYRgux zW|7j>cKdB#5~lf^dgq;YSkJ;bJR9adfwd!0$j^7D$kaf&ZAN)(qRe4FikAY^CtFE)=XA!)vRyzxWdYSrfB{4RoK*L#rwDMefK*INr3iu!5FEF+=WW>IU~xC7TLvkU zM-C$BG2aDUN*IR}`4DixqgP!cST~jqbEUXt!KU_H$z0eZtFfxMVl)e|b^;QGix=Bj zgm`=Q{=3N3X8|X}pp&hL(6ANDR@&OTZ)5%qrc72?B8aM$L=NtgLWW^3;)Xa?B(W06 z6F!Cn%ptOiibufHR&Ehmp+WnigOWh6x#a_A5+dEe{^zZoHioFM3@E=uqkHITpMo0@ z$}WQ?XC0|=M3OF2U5$?!{f36hcJ|y0nYVk~25@B0;BQwf4%i+9x5?Abw*LKx?5twV z2Ko-zx#L;6Vf$7)d)^W|JQa73cU)x?pmPmXZyN?tLoYmOBRg0xP#;}MUv=-*TRnmP zFvLei1JFJv!>II}sB~)zXY}sq3&X!FXE{ zP$6VfftZGC*WParJn$fZcPEULxeCBXjAQGj$875#{gIvX@!MIj6BZ1^5wCE&Mm2+l zUI%kd)e#tv!c1v~%9J%nlH+IHUO~04>W`dX7GbtxqiV*|UGo zT5iu^gdq=P?;GGi{my`>MhwcCj8w5M!-4RD&ZjU34PIa+3Y>OZLcZe`GTkzs`E*Txwri zdnX;CJ_mb%kNKrMOXOJfMFupTA?9)In*e=?e4`Hs0B?j9D)KT2!6(vJv`1|z;oNT* zL=fOBDN4%~S1z$zFfej5w+zM&Np$a#@Dw^t)|jhry3y{q`%Y+wZ08&qncBnasM(;> z)K>F%8#iurMy=!M&d>^o>cS-#%(NfB1h@~ga(Nda*LdDa&}7@b0p`~x&^x49o~ay5 zQRVpBY5;m2%;V;{-!BqZv$EhkK7OzO=Ghv;FR+TVci`X=d+miRHv8;)o8ESw9WFg< zL*IYQW-25He^W<)5I_QcDJ?pxIPNql`9q6ZH zwthZ2SCeK$NneB{|8Ss8*~^AJJyCi3prfi>a)_+cKvHea_)=EnmJ}}OP)T!(65`?; z>fe~2ue_%Dl9x^Yq!f5H3XFNc3-7N~Q%X`$@iot$UN>!niZe(v5!cXe!hCpXHJR>Z z!kg-mIIsdJ%jBI`b{z|ju3oW<@KbC2<&>l#mjW9Zv`GkWL$!Y9V+ig9=PW3iKA*vL z7+M!xp$pa0J8oEE+tv-(3lD#ne(0?S{cs6rKYzBhUAo9R$Ki{G%1S+zt3=i3zpB8I@<7zF2>5rzJT&W2mA@r6-_+@_?PFq)7X{wlttq_VA>H#e{GP+a0p`n^IDgI~5x zV7azgDl&b|U*c--`Ev0958Xb&GJy2%M{UmK^9bAZL$fCzhS-3=?g#)c$+aQ?#2-y_ zP+EMb^%d@h8R-n%iR;vy}ZDTDyM>0n{;HgSXeF3X4Yf2UYD7Ry$p~Tu}v5s>5Ip$98s$&^jhoOoIY-DxZwt0a8}?hu!~?AB|Onn zw{B`X*CSm`%SmRr)z^?lN0=WjBjJg@?&?7K3~JW1$7OA#?;zSdp1tpX&nhdg z!*~i+r=B>}%)|7%(O%@EWY8|1G0~pi^Mt);@qGL4hJUc7H+Fw5Q zqX~30;=8;!RR6oj8maGHC%rze;qnKD#dBN68Y6vjPA|g93f92_qT`X$p4<4aeFU)BdERuK zobSa(1C&G+Dn?#wpJ+!$=p`VS1Bun+x>g_u_)09d<5C@<2@B^(e!?5vA==@WJQq9T9>Zu;*OA+HU_ss&6n)>litJp^xtR*H5K%EOQye8R_t7^prn z6rN2|S9?3snJ*PzwhyoPpe?`Zm*|I7oqP;Hz$`8UitFh{Il4D6#Gx$9>#&t?T$NP< zq#E|vmxOz%>)071?MONWNZi$dcI79yV&(NFRkPHYBA13FK$K*m_?ICBn%`a8Lb{A< zY!OGpr*4HSYnAe(zEsqf4I4K2nDq=DPb-1q?D?12{te%H^^z9 zW*4mf_co02O+S%YM);5_vZT;7B-huzzQ_L8_xK2SBEGJ=#yC%Pf!I!`lu zdOk>cR=7-OFhB8se)n6z&Q+gDam_6|c@%1nt0Z{qw&}CQ#+_v|R{e&J?|nV$c-|GS z8}&8U=p#UHp&pT`r31F0ei{mlZNSr;s2@r1j?Wjw z7o20gSK*5?NFiQU6Xm>VZl$PwC62YnhdB}g=KwTi=!N{!+Pm$6uYAq!c<`$#=-8tb z0)BA&-@x1m`=mEnk|NtT0ghP!?ePr{+nfb6?FSFuWq)wbfPHAyGW+8{_%HVPyY98! zPrvA)wn{MmEYUO?K0zppLeyQ_M?$~=oz83ikED)iaBRh^#gBC82Q8o$WZafH7B53t z3NKi+z&`%zo11k-^;}?(DtPjwwdEANSxJmvl1-e?Ql8YD3Ztd@OquwPuyTU<->jK4 zZTB|Rp#0Ny4b*%Zik4~;c(~zCf>I5n2$|E@WF0BfeSs%swQwx%esEhVN&_lyRw2_OX6a+1qDH1%`1AZ0RmByCLP!!H8is0 zlb#*=Lbgi9l6tN(QpIvY_r$Rc3)}wj0D1e_R-#RPYH|a7tLwcG71Z?g(KUf%UMy9h zF9KDZ0G^js`81^zI7JGKZNL+e;+x5?zf%4d1@<3Li`jZP-h1D1F+gt}$)y#2+u|#y z^U7A8@rNd-jW19DZo=Z0nsn z!`2a@B!kLl&0V+Kf`yCxEB)KspRpgIvDDm`x=}|Zst6}=Z&ZSOAxnKk)O?o~guvb@ z@?c_M4WJ@GkqT5yEa@i_Tv46O+DAV05nFTHowOx_$%jydC@bcv zBh3YBPLE*7c~(zw^&)XB#k}R8Scj1-L|5H8EOlVMf7V;xYK1wkBgzSYB1X*kzqBW3 z=lwr_V8h$KZwJ4_M+rt73VWvh0;}GtTI`vB8DLhi?OQgr(2Z(H8n=Tm{TG<6T)EQj zy6diRlD`^rRB0+Rg1%N(zvbr7QUM+DIZBC`D#0I~heNwJ+3Vjs+X{zEwhhZo1(j~^ zp2S*=-L{$7oTZM5em~n#^OlM5BkNYFh6jfFt*d zefF@GQGv<;E00@3p7Nc13=CxWP{8oVkRmWdx*b;&;#=q7h(G;!dozw>Nl zWyQ=b_UD6gQq#LnpB@`s&!Z>_+MhF|x<+Fhk0e&4+}j|z$y_TLzV0pma=Jh-jH~83 z$Gg@Lt@NCz(oi$o@N6k3O(_Lli2^)^V?6nbGfIO5zx)-_%N<{Eee^1Y_blc*ck&li zC0(TxiiI~l_Fw+q z9=iQ6?S-D#*pv_7Xe*b!-yT@^Rn%oQ4{H4A_FeYYRUcucg4OnoepEpUPK}yQ&dwgO zgkEQf*;y~a0Ep!8j6oxDh6)cAsL*bMc|e~V5r+aK<+tYRx$z}mDIH`e;!GNB)|M`1 z_3w4-7@a^3KoPid(jBffa=97F{Lhc$9gd;E)gi`nlKNj{!yj+ zLJ}~{ojnJf9d&zxgbR$(xi`ZG4Ek~g86ojhxajjQzA!5@5!>JA}jiAzg`9a_|ff(L~Ll!VXi zkhV;B)n)G&^G55r^ff#J1v_xz#dh=^R}*XVCFYl*BcR{^B;daL z#{d=2nFh`?pg;ryBLOr`K^LB7#^$7AcsWVVXdCoQhFb^m&}b-JT86JFdAO*s(}Q~u zq&vzuAvsc|Nz=d%S_+1&t+`L&*}^{_xrJt*_%E8=8Hgu-h6o%?3 z>d&^?Ve5Mer)SORBa!XgzTJNNW1p~fU%AKTEPSoqcklhS_0jb-QnPR0bH9D>K+eX$ z`y*!En)HY9z>r`k*mD%H?HGjVi9v}Gs6NH&WTTD}?W6q{ueYw53owd+L8IE!*R^I_ z@|b{5Ece--Z{2G(F*+p31((gkLNjBVH>`Jl-pUbGOb%1X8O z$(ui^QVs~MTQN0#?W=8PmXJhAQq&DM3S{pCROCyjq!}fRMvRmlGQDl7j)(T!!?*s4 z&78Lof4a-;YxmxRW{%+0fB@^{*uFXexV0j??gis50rtbF?G&(i7+=Q@q@5b~qAJk$ zgb@+*WL|%grMcT{mR@BKJP3GGMn;(gJEIIeLJe633?i^eYE#HDt;r{V6Ju8rT?C3U zZjlO9MlF&8vw*RHvx=IpfSXBOR<%k5EtqrOxd2?hy;SeAh73$-tDkWkKFqwOq)OD+ zGOB3+bb0*fItf%=9~rRyPj0c!CFcWysA#$WtTAEz9o-zU{LzdlR(^83y?MrYcEOYV z_TGyM_UCIJu=L?quH}ALE3wex?$2;j9xOtRV*C=dth>av}5HUjIX23x^ZWC1L41( zAoST2n}5XDI`xTpGf&llgi|}e*E(_3E~7e>rD+a{4Cu3QeBIan*_>xQ1{&D zj=6XA+ut0r5=BA)B7bT4!+(vxAxAuJsK8F|Mq7b#EkU0W#lpuF)3$tAdG+C<^lwUmQ=mY2noptNnOa1zAa9^E8tw7kdQKcK@06b# zWnZC8Jn!$n4qP%6swCy9Op<{S%1MsOnApKY`D&$h%`LHdsJkTS(^yQ<)m>teK6w_t zn(w;xZd<+jLw*f{f!+7@2kbw6=J)ZpdfuiFKZ`2#FsAr~nZmj=0|S!PsG6Eo?YF0P zY-V|!tF3s|FWP55`}?kfliG5aIj`{;3=APiRM8trDpZi?5fo-4k~}4mpn{q`_ce6B zZtJy{9Nm>BQ~07JTGai33=zPQDR3*PJQacE`WsoSmAIK==)S7BE)+)$#a!A^mKI4> zmS^+lx@%Y1x_j;m;F`22GOA4_HK)SDB7N~|&Tav#9CRTW$w|RJSO}#)NP9K=wp}UBAEz)P*RY$A|ESd*B^=^_{mXkL4IU@ zXUGu%kOXQA7cRu7?-n1Q-&6AAM}W!*=(Q@t!w)~KLrx0t!#`h@f-e_Yg3jxi&vHr! z?HeEa&pbQ0U&slQpyU2Qb#bp<^y{Cn7i;4&w(PV5A2`!+aanTq9NWRYcy8uA`#Q{H5f`P`rd@;PVkwbx$t-^=OLPIj!U45Jrz zIO5?<*7R(7H3@5pKGVCuy}4n%U4Q%6t-9v8#|C}41ddol7h>`d7RD*;QBP+jN(rJ$ z=S0Xg5yT`>FMKI;9Go7-gKdWO*6vS*3$2G3@bzIGqOm!BBWUroA+(v00>}@F_=l z5o^Bl6BPh1|Ea?iDWW_Bdj5~^N8z_$jfg@8zyzHAadCPm|HTctnY>fOI_p9z09HBl zaV?QLwNeTRFhlJIdJs{^#>Mqz$4&J(3rNp`a>rH$66O}3q?M7*f^ zuC74pkc3zfF*vD~eOd^MWE|CvBaIA{vz?kx_*GS}ChhoaA9y5u0*T zZEEVZzOAKo2L6*X5QQKA$?AV!)pS-wsVaMS69`L+@;^F1LRk9q0~qDN>@Lj4Q=>U0Jo9By#%z3{cEt{!z9=JEmnAfkG8L_k`m@`!YvT=bG% zcE{Zy$sYF9+^1~8b8pz)D-k^o8ZK<*?`+xlj{WfJ;nutEh}|{%b42>+;rftmMI|C=6-2|K4%xr`laPPw%B?8tyrjTJWAU&V@Dq~2A3YA1wE-fkva8%-4 zH5%b=0d_AMgJjo;C3~XR>XRwI%|@%^{-K(%Rp6U>98Rz~BNGR7qS;WLp~3wtH4y%d zxHi;hwzDl~s_j5arhRZCWE)S`kx3nn6@sfh1V&cqgk>Yz?!b#`Z=sxJg)Q zXWmcpS@x!~(7PLjqdyt4Fbzqcwp6s49mi{_)eYU`|vrJgOsIrYq8&M-ERe>rV-d5>wycY;u|eN?(stlIr6Ebo zt2vWZV&DKC88PpfFm9|pyLh4FCl{GT=luM<2fRb@M9??6O>EeTz7H-<`QK!%>SN+r zO}En<(x=k5vfZ043%%W-yrH&h`!4QDR0saRLbK(N`cFL&Ls@z!JCl%Z)vQYxgBEe} z@!~dxYy_YsUi2a(6pVD-kO#y&bck)e_g=pfnAy-I7)K&&Aw_Y$L+S4xkh%vcpe6|s ze2$&V6%q%j<>%!y_2ky}O<^^LJYC=fVg4X+(n+YxwYWyh@6pM6V$GVIongB+e`Gn? zZAfKx9HMEEotpX$#!pCV)-<7})DFM3*6I(@FXu#Qm3}I_hs4&7oOw^92n%kFn=sxc z^Y=UkNNd(SPlOuQNi&|%#?q@#TXN%Bt7#_u8?HNb7`4a=T{9-)P`KI)Q>{HO!o~+7 z4p*qtk=^-PL0uurKPe)R)TSQyqKQyBe20rx&@88_`ejxtz0P*|6gQCL| zIY0u6&c$&_Pq|n|5EmdPYe)r~j+e`T^c^C-0i165A?OdHi&0!FHKIR3VTDza6E&8V zN^?_+b8$5yodzLA4!v}CLP$-7;pzdfxMJ!Zw(gl9LtPUBjBMo3EPTcu`_Ut|_2VL3 z1J>B4qHR{TW4je^Eh4J^WxNI;APA+NLa~PtmnDP~EpJ$XjTzF>7A|{+_PMP;kXymm zX4&b4jt+dJ!I3{)BHU3rh;y&}*Nz|cK2MxDo(MBbd>9tKR|;KSfyb! zGY7*92ww&_R;(8=Vj6BSl|_Dg*@mC5dbd? zLTYKLv5ME%SbF&py98!s!!PdhelR!;I)MBn-8Cgjg=2~Zh!gCMxkQAk=hSlGu~O8pHKUB7^|q?9s;_u|*4iZN>PntzP{c1}{@=&2y`4 zEL8Tukwb0q@|STvD7A#@qt+Jgr3H?yp7#jvCBwzF$Lh0BZcn(7e)j5`$kq@%;QeP3 zvg~M5M{q635h(3I7W4I%6hfKBAbJ&01fz|>L4Nkk+0OaM>QDf?1qc}9ke#*!w7Ce# z@;MVw*KkIU9b+q25k8G7;ugdi$_(D2r-%lSvgTKDGG&S{>p&TQG&84rut^=s9DEm+z0XrwYC{f zN5(KJ8j~+IuTd;iU5^q%dbO%Kq2TXPXB(|kX1eX!^r7v1>wPPgPoX$NneP*_tHWn* zw5kT&FPMZxFn&5ZuS;<+*#M!V$vA}(RU_P=h$f+-Q|C@u*Nk}U)vJen^!jh@_K6d$ zwz`slJ#Z%k~RCYERElm{i(gh2ivR-Z(^$J=ke9lhfM>|R1Pj?_r% ze=tg&4gH|Lh&vE0)?ADWq7Jcj7Oo?8^fRqZmetg9PjX%%c})xiTnolJsr?3HO&hZI zjiq+>%~v4|>fm0T^zuF9OGB%AjhFKmBER(!z308ss<)O;+YCgY+NW*U|IOp&aJlZn z50bd1NP#jEF+0 z&7NsvCylXL56`q0-rHi^-(4%L!e4{sj=I<;PMBi5-~baFYph3lygf%&gfX|`3ejhf ztz5kniW*Lf_eoqRQCl-cGR*)z>6vQD&K>Am$Q3tmkZsto1%?o-MmRt3pzwhZAAL;_ zcPp$x#}({Z@iUn?8w}!#g_GU7wHQKxAlgE3KuZBjH$VZPOG+k0qkIs7nC z*#N;@6+5uTAI*oLR%@S88>5XI@5SPb% z$FVjN3npaX^j%fSx^Z6|IJ!a?Z6<-})l0aat`}cx`yco*>jsyIn6RlHJ)uOx^h<6Z zLUw~m4Yg(0P7MPQ9b?p_P(&+W{>YaW8-O@d30}8u-|cf2RN!B6HeAsR+%ajK{R)GY z(&F7dCnyb7fj*^JH}sjIj@h=qvfk2Jue^*T>x!|-xt=|&HtAY>ZTC^!8nEsJi7V?x z6V}4#;F!*wD!0u15%$s9lh&tKZ@cu1-RuuLk667#wzM8bbQ-I%X-FCuQEimjWAem8 zEOKWcie6?n+;ju$2hRj&=|kfmZDU1salN+IMaY>yA;7-FMq2iWt1V+-Kii4>!zn_j zDJE!)bg>W!f#^8is?f5g^d4zFy7#s2jVJBwdvDQ?8rD^F5-qKuEIJddpa1p@wC<9B zdv5;ocK}#|yr&aSTLBinoAAcq$OBT`**HW_0GGK-28;z8{6gFDCDlW(r! zI~)wK&+Qk4{3rr*`g7pQi^PFAv=rn70VRq>;<;k7iQjwQEH@H(;K4`j+0`#t&tW6% z>aYHjJ-2kJy?(gXMo*k!32k@U=G80c6XM7<+wGa+kF9WYp!b^U;*KX*UlW#p5>+J=3|j^;5|0+*FSu&e+91r8I04BRHAd$69zu)9e&>&L!?Lnng83Z6sDH)w! zTMULOLgyGKh81NsaN+fq){J3`#@{R723)B(`5pDGlc6h< zbuhJKkTN8(k4~LCY$Fk4zx95R6B?OF8d};nSy>GT6XTf%<|2uHDq2f|VwEB;y{z!7 zh`&Sjl_`_#<)w@4=38!ythM&M2nDufr0)ucc0OVa?TPpqkH|I_EZ=+hD0^e~G26Rs zlg0PH1o12haCyE-GR=C#rQ&KegBVRUq_xKnF~+K!E9pLai#gHu_oLv`q%*;nV5)<8 z^QXB^8%|X4&F52}UUaXue41uJJF2z(x6D8QkkypV9AKTpU1Kc=(d)>0SIEwBR^&uV zBni;*njnCEAGWvY( zl;{kR6owRr*e@_cWc=ca92p6)%Ua?z(z!aHl97l(XWc(XV3_~JD^o|1O!LKPl>uIp zs*qnziaQD-or0g=isf*h0PqmVA}R(HLJFu4tw6wOs7+-r5a5%zSDy+jEj^(l68hEb zma#mG1!PA|{wqO#$~GW_i3E^$9EKom8p~}b^_mFiT;1bxt4{Ci>6{Wk=pRu(XUH{n z>c|oL$~pnG)qTy4XNCtU4j*{`q-u!kb)Yr{|TLNO~v@TXU9?0C!nUc6Y?w&8bwJ~;zbV)wj3h_l% zMbJ?n6Ntc4$(mQw(YTZ>66wa>L04mloQ={&vJ9@gy6U|D%XnVq9^n{zBe4v2cPT{pX)Y!hkIMv03-hk+wGE_HS7% z;&kQwi-~1!rR&3>O5$#1V%MGw({K4xwrHI+ze3z3u03D0U!sLRL^ezt~f9inoY#5fEPhY0|(%s8UYM@5!>ypUuy%tGvBr}q*-I{ zQI?jAZO{HacF$u!vDX$avNcPevCTzWZ4-d0 z|HBxfG-ApRHzkwwI+BK_!R4h$v_-U%X;Y@zlBa*}<7|N|is?1juKChe?JO}Ln=$2= zp`^H(c)rx^*=TzfVqk;w_Yk6(tlzXA0F2nr*#hQHGD*QT{+vz_uH<=%7oC0J`oKX0 zY%9rhgUKN}2uP<6_YOyVnj^8?AQL%pi!0T8l)*rpri$89`X6x|D$bFMgCY9Jn-AY> z(;s@=maJN4VJtv>${llYUjdZ?y0!SYok{B8l1*Q4(()wX!Vz+|gAU6O2t+Ipf?enL>krV6!+#O6C)f0-#Dgj^%uj>3=&4g|8My^DuE60v zh(psX?0{IHpm#U&{%#@tRJw&gKr-T~#M!b=1~`bC6Ob?@^K2Y?I_Z{c>BGqybbTGW z+sU#jkYWk}2$Joh9=JHvowbg=JKFK%$EM| zAbGM}AR`VsP3ILpPkov$GT^cSXE zM*b+Pf%Dg#h>%ke;%~vIN?dB6>0h<|zkZVXAWv8tNqQ5pFLYvi<*^C*JZTQdv2RsNnK?;lqo!nVCpp#iW zY+qt0JCNMPPGHETt2DV>Aryrb)Ni%C#%q7$uk)hDFi5O8N`x04TzJFvm&E zNep9{JRZmGrON>N07CvW7mXlKMFDYhc?^N%ydOBO%fSJsXLOs37lE{?FLhlCMml;& z)O|omNUjSCRo1;vj&;Q!E&Sn2*j50{iE3l@N9oX6I)k1Gu0#3x6mv7oJjg;`Fg6~9 ztpEc7vIYKATSzUQj!q>N(5fX%e2C)8G#+I!)cBI!#UpIfr^2=3$0ra?bBL&0~K}2~7F0tfYvwa_1N=!9eE(u>_AufoBBPuR2op5S3wZspNv(n^jt8U-N zKJ$-roja8DgciL`eP~4`>lEj#IXqwJUQl%PkM2Zow0?dHW}ubB`wJFXXDB#20Y}F< z4j`YmDNqJt;y5agnd{{Idhm~12>Jum;xo$4EM2w~UD#BcIG!xw&;17EQDyBL${=)! zw+TYibFTUm)bJ9{|c;KmbWZK~!-1m%e6gw(qkK-ux|C zq62_mSSZe}8ha~NfC;vz$_+NR5IhMbKPI!+2*89$W;GtxzA-H&2N-|wkLl2=%S0P_#pa1BnlD-D~DbTwQOCV^&^CY`;3Xqvfo%TiGaEOf7d1FZen%r?-Wx6Yb(jU$*s&{u$0ss~9QT0Q!p*Z4Ke#3yXgGn(E>O zbuX;b`u*>723ir`U$Cw^D*;G~9w7aST+u0u!Kf z-Jgsa1TEE5dLgI`AQgZK1H7AwmQn?R*^4RoAtGP&Mm&{E)`5z{dn~K(#rQv^*&}oQ z#YPems_=%ZZ26+aW;@Z*A=-TI<^N^hpFh{Gzoeg~V3qjDvPJePBC;t{CffHOd&m}U zCj=Cfb|Sunjp)B5ii|}(mEf5iB>GCQsS~Hzq6N=-*Yr;qYP}hunok&A4e*|<1mSA+ z8z?^*B-uV;11-jfFC5#Is#%sYKjCEXWRBqcy-e$$C?R+Y_<@NwpT+ucN(30^xeZ zkL4{HxGx}@hWKb^Un!odOC2Cgl))f`-{J52Lkljlb-Pcoz4lvj-f$k`KKm&aF{Wli^C0WZ2C!E>9HyMr2M)i)j&Hljj%|7m z(ZPLSg{1&o zIQ&Ws>Q>qy%Y3xyvq&atV|n$D3EuA<7iwdrc>H<#Gum)~UFQaaih zKu&vn)UKO)yY1b%#Y*?>z=?aU{pham+Kp4EW6fD;{mB8h8>jIl%T`*)-N&u}gdf-u zkWPIap}f*0_7YbV__xXWzfEo~0FnG|J9Y<9h-?Ne;!1>6eA@U&5L1OPV9gi+#i0M2 zf?>}>40|Mk6mW|L*)_U>2q2F7Edu_`pLAEk1q1U3Fz#4#&%qf1bd%tALl}nO>=Btq z%_;LvWg*8xIO`PzuWkTIC&Gz@;fBFAF0%A=HL8vaNp|&d7hy`2C`7D;v~3#C!6}l? zhjFLmk}$USAdpTl-#dr}nbC7FK4l<7fn63u0jnhr6)w1S{CHdS{0nqKh=2>UD?M2h zYzyHIBlXan`{sh9g$PxZ4vQ0_IdO(cO*CuP{fKs%0xC2$$QuvQC!+C!&TZ_Y!yr=( zQWD6NvHSROXfEZ|Q=(Yum}!bJxNjWuSi^)=D(C_9hjeF^b!3On%CfeVVe8Ymouwe! zZb6i}zXxI05IG`rw4bbf-9orGxPcW!kVn!H0pjBglaH{k$jB5@jZ0&>~CTcqeMKU>BAPerwPwKHtID)_?!LXP_0~{e|m${;Wj5L=RB} z*$MaPQuMZ4A71!Q-E@u%QIUY3kOGKJdbybo%(WL@{f&*j>Bis*4!eAxfB=p_0C|BZ z4S+lMfjKt+kwl~AsW3#9ipYVRLkyfm98T(k3P#w_E@XdL{4))K7>&dc z?K{dw-TsdNy}-z&3NcnHepYSi)A}V(k@n|98<5|V><|qYpWvgW_INaozB~0#-^8Uv zCPb6!|4p0xWvoqCQ5VF-e|ny;%#l_`g-NFm;;w~XFCH<(=929|BEm4bLlGYme}=^| zYZcLD+WxJ!ZT6k^)GNQWZ{BhfmuWzg?0%FOwIsEpN&dqEGNk80O!2H~7MUqLyFEHU zVONQ}odZ$?9-OO{rpQh15l_c~WgVY+XPa$s!5{)tZvjsVA&M{pA^LaT3*s6IvfETd z7z?gShz$QBM%;?PvMrMQ|hcef}bl~5Dn%O>^-xe@5T^G1wc35jt)j(RK1P`2-AtO@Ryf@{7w@;E(r07XMor0u zxY`$xb5Wujb})Im4+0!aiXCNJ+61DAh1w5;QrcbdD0#hcBx3~WFF^jK19&j>hlBx6+P9%&R3)O%nXaihg42DSR zQ;WpXs-ZPU$LShJI@7sem{l_Vz04c0;N2{pxE1O}wt-E;$5B>}qFFRdiNQU~J)E6@ z`-H+twvhYcc-2qo_2MMzWz7bn^E_3u-8R1co(Gr?``Y4=e#IBa1BfdE3SNc1%f@G~ zSI73Yi;Np3M^C#&WIf2ailnmfInoJA^a1t;^tcDO#t&S5n3;re1bgUdt>;>`r+!7XOt?88VIve6aR;ua#u z@=V$|L`w$b(xbz?K68}tQaSo$-2WMiL?l1nkC4y49AF;;2R362HALryhkxKZPs6C~`b!cvd(C zgbIi1h>e?~1w@570>MZ{BE(qrlV=Ab!Yw8+x5RcrbjkzhZ(!PFU07d(**|@Xk*^qB zQ4@$l30uW=V|EBvivdtpZ$7)*Rnxv_KYRXl?jia`Ka~J-*Q@nrZ|9D0s{>(4WZ4L!Q`o&s z40k$Xl+w2Pq>cSdf&J66MM3|ywi0#ImzFxXN{F8Z#Ow9sbUYMFA}f0VIsdY3!HP9D zbJlDSz6_Djtx7!09Qge4=|A-8SGcP4*NP5(Mm|mdu$ye|r)j|d?PC>W`I90}O~;9o z9~^#t^#i6$0#_;$$w|;AA&meVq8fmGgRCv}7*5DQZT{j2`*haYwP|C+NZGS}r_#z$ z5J%}V-~fVSEzV^deq#kh&KNv6-!`pVXGh+B-_E}CrX73zMM5&YV>Mm+SXy=mo^7$5 ztW+D>yQ@{4JWP86CS*keSPJpPz#YV3P}2gZ(1?$oqN2D9oBEVYM1HuJvdS7eaPWxr z%*S%tg_iVAxUR+?gT|3yn{^U`6 z>-WFI$LoZRoAEV^%fEp zQ9oMn8*?XjI50Uti_?e|5@T-eB6;dheu`xzV@d!q%D>O&j(PHBW7=ZiT*WaCDi}Zv z(ZRNC>1xfc-&a7au#6$lLkamQNU{*y5bE{q-N#;j@deivsYK zpF9EmH- zc0DcglAGXW;rJl{KwBiFt+!MNq`b~K)*&l}@N@&PMBQ#{e{ip*fA%^8N@tL^iu6Dj zth9hk6SWT!OV^7+VZB?J*K0-%vt&Ztz4!Z9>>s}KEnBzlZB|Ybpe2b+Lhv(kHMrvy zqW6Ozt^fX=&p<1}`%4!%a*#NE01}{3m#RQAZq~%n(%cNbs0U3WRz@wS)Tn zY=UgKDPJxBLc4KLx!ZSaw*gov4pTfv078o@(TYTM&ZPkT1ONr`iUBYKh{%yg{o-xw zfms+5#MIE42FtwoQp?Ec1l)tGB*<@4)kz!Dx0@qXaa9QbcyJ$_6;VnAsEBS%&z|Y=k128K4ZIfZuN1!_ttw>+W|z}BbRhFxKO~gHt{~31uPXHTDkpw zyY=&czRM;~iAC=p|rs3rxLMUdq;-+o(@ z;-XotiHt;KF&aZ1>?^sV6)^kG_r6Vrg5`D^cMRvAbWsyQaR+ZvFEc$plK_H} z@b%l@`L-=zxztXVf>c-+1_-f$_?de`&iNSbti-=BUPd?)QH#^0*FE7O zSSbe=o&m)luzYH7L zsg1pVxXj9P@@-=|)|7BzO+1&Dk!qj0`WlOC*Tq`8<)JkUTZi~YOCxmK;4W?KB9auB zlYF+Cz5Ef@!e?<^NW1b@=A|9aCo@J!5B5Q9GK3*|(nNH4G0ABd9J8Mp(}!@bo#H~) zvu&D{o;hXtAWacQfeEZHo0idwW=AI{Ac=HI3*A~iEi)jANNf2^WrM>&;@ zD1~dXKk$N6xek@YKC;RqeYK0+0wa1k4-0;94227M&^alIg($9fLS81(o{s6tl`Cxm zK4Oz6Par1bDu1s4m=3V`MP~?s)=hAUD_5^3M&%^(k=;smZNzkX5h-Ar_N})ng7hY) zWh2%MS!r{HrJd|*SL6=0SJ!>udC5W`v7Ej`h--*24+EJdD0mrO#Nu=uk3oQpL-f`L zfOG?#RV}8b)iUtN>SCubEJ#dk&-mev;GEU3FU_ANi}tl~*VJvjm0I31Y#u5BD?BTq|&brGI_kL`}yLT~1aF--H9emwH zI|UaK16L_OtYo;N&R9u){Q8?rRUH{3CfX`xY*%6WG)E#UoG4M075-xaxgKM~hZMMY zbw|-IF*$IF)Mp-}8NKynKumyJ@pY3ZcH@?BM~GClY{70q1e)x-!wYF+&N@UwET-dYef${On14j zh2&4Nfkrwdlss(22)hrfUN4$+_L}}vV6}<(#Vu#wsAC?s45TcpQgL`Ud}fqwc>i^) zszBG6lw~0}>_&Vi+x8s5{G-=nB06U#SUNh`QzuVa-o-eY?<%uYM4Sp>An|MpI^l$x zGuE~?#Xj797z@kZb|$$4PsdqD0$1NW<13bWYL^|_w8@6_&$T^pbt&ySTL!whLH*F{ z9Xw=jz5AZkfne(~+^Hi)QzLVd!C4ApWvaQ6flm_|>H{$)zKUScX8b{=|0~A|_zM%i zY%kw;r(HL!x3!VOIu@jpCQm`%%lb2i^fV|Cr0hzcvtU2yvIrg>zGw-EoZwe<4T7c6 zHE%2W@cD+L&+_^Ic~AQ+c*priqV+C#G$5FDA>dCXD)$#gKhM`yAOD>`pRX6$LKpnj zc%#o=*oEk*)#~{^>bVOm>9-0MqL=@uuHTHbr2VV%=M{qM|3m+_BD}wF;>8WfoIdNi zsYIQ?*;o`bVy^%~vgoo8mlz50OBU8~6~B1~pr@$ts>8-XUn7%p{m`LM+(2z6fn(1I z?%%}8$=SHc)~tNqCKrykNd!V(NeUp~ms|6-C^4xvm&8>noR(!vmV1hz@ngr^b8A=A z4Wd=Nx|F^ks*+I)0e68lC>*1RfDq5Wd*-YS>36whrzcon5d2om(Rc1S zYDYGGY%A#7H)lO)$6sGY&c77vhcDo8vY#t?X~}^S>)f-zs?asgedqyudg)p_3=*!w zoW6|tR#x=}5}T$bkyKO=g8zpgo@|8B*t#8`!3&DGIZq=LS)KqXgl*!~N%rirr@f|z zq0~N_doj;}QA+?6^}CSJZ!4Frc23Kk#F=y_UO@hy&L|A`$Q%tA+!qn-I_8G8);y?T z=3MKjdP1z+V3{P;7IFe{OAm%&22=&_Mb8J|Pbad<@AsU5ozvdpx}w1V)LZ;J$zsvn zZNy;75wbQ8>nRbeXQE)dvFy!8GIMCG@)vZmG?iuia%o;Kdwkq99-=eyy}+s4t{!LY zy0*1*;Vhmet|}tLcJ15R+Z7>O_Q5`@!}8RKgi;=A0(GIw!|@ygN*vfztnc8Fwsw0t zTr|2p#??Y(msQJ_S?Ko=XZ5vq?d{(n+xz9#)Tx~vF0ZiXKinpPDb}pr9ho)roc2^a zk$uugHk*n;N|&D9A;L1P=p<4K5MmR1uZ8RsOsJ!U5Rq5bA30+qXME4rt$oI>>(id+ zK-Um8lQHC324|~1Axl<2Rm`a}aIgjV3k04Bs=YN9C#a)iD}u*K1|2HZRe|qT75zmD z&1q)YD-f@Kj@dU7wQ9{(K(cZpk#((PIl(FCAuWK`kPj}h-u!8U@jX~A>hm7g&+C@z zPy!Ms=uL1%|MHu8b6A8FC)&M$>b1W4>r^rN7kR(m z;F`diO2p>tll}=N=ous-UY8H`U1L%CWE{cozxBUF)JboX)FlOQ`QLhi7TLp*9(pqKiC`&!2BzR1S&VM zIOAaPeK|%f^Bj_KQXlz{YPh!M1ttmql|t@#1s`DII&+7pjIW<@);S;?;5>}&ug zK2GlF&LNY5ggAvaF#R7hb((!)^p#jxZm{BohXI}uAb}HdCK(r+2tOr9?2*I!+om0R zIMi@@9Q1@#!j$pO2DreW?+9`kvm1D@@oUk`h2T!MSK{zoU2A#0hhp}A&Kmk$Y{|_j zBys(=O(UpsGYEItisxK(r4xQqNRMjNN$A$w>hJiDrG_fWPe_|^`a_2d1Bq<6 z9(Vo#gpR?-&X4Wn2d^^*9Lw2flgVhI*qZ9%c}PV^wI}lP2NLYN(f04(Pydzi0P9=z z0;n?x1E5_+Sft89of5-Zb|26KTByb@&&{#-&xEZ4-#g_pJY5|^^qOLotYJKJ9z$?| z%1Zn=3H7%7!~x4jthoDlofARH5GiRO#3Ud!4kmUQ9rUm-eapTycC5Ym{>O}~#WrnT zZ`Ft-WsFjX0Za^H>?FqGiE5dTB-$91+snG4mppLdv>iQqoGHw-P#qSz1hW>0t*AE5 zh~1k(93i;E8usW-Q@(5)e*J`fd;E>IblGCdBYx`WsT1u5h(r_D%zIkIVY4S$%E%GX zM%4_kcXdx&gbW}}aE@LgoOTdCkc#xvw?uFk#2AQ`eZxZp%Edxx%@LW43pm-@OnQen zd_|8DGQdJQKziy4g?*u&7U>M1AUr)6T-1%AiJ-IoJNSpTRM1Hx{S@;c_W^Nisc^u` z*qw=ft*%Odk?8)oE5su~~&%Lt*xy*7efiq}FTg)ng5Pu8Bj+FQRqYR5(FV@heDWB$241Fz7gQvf5tyquS>47odo%=0dbU(HK0SE0WKg=J1y)Z z0WA3eiX*9qV8ScTVt2f2dq`kwO=lrKngHf6*cgxrX)6ruQ_DZ>wjz02X?U^-TNJTh_mr)M7e!%U8n^izO&*bO{&j> zV+2K^kx!=1p$IjkABF@&?hxXu$w@ z84exf>-!ChXBWYEU4?%mU;zni&%F6E@2lZS+Tz@+Wp5|)Em$kgy^e8&AdV57pq5$* ziq?W_!NX3R>AE8nJ_Q0K-S)zFmYP2*yAoSB^nBzxA3msHV8QqEw?65edVm0%JGvJ5 zkung6BTIcv2yIvX;eG?b$eTiKAYkx#%@2~xyzt8ryVp@MFxe&;! zMw?NaO3^RiYU*`blA&`k5RpisUS{6h*M`sma;a3WDnl|kRwNl zMnwIoIHJ^hK#XhQ2p^a`*AC}(w>>-e!uifpr`|W3UeT8;4Fd}+fJI>;I4nfUIAF(!VAq+{UrZU@jFGv6&H+{xrd-~a@c`qW# zi0)KGh#y+kN^vcl0gR&LhoI|w_St9L_(Pnf<~88-_+%;tV5HwHoHEsxt%BOr}n_BV2SQYy6} z^Smi^860Z&{=IAydNWqT*G{o1!w@8c2llt2BQA18HEGfWn*_Hx5UX8@Qj50jvf|=m zjGup5W8hUeepr zk#Kyly%-#kY5NFX(7jKtbf%P_L%)*^Bz!^dVpDj>&*Z52FXR{tygW=31fe|ZM9$|9^0lL>(& zLgh6QFVb~yAP;8|WIjzjCBpOo#aPh^59-*&BgT+}c?+Tz!_Y&PhHhdHvh)DNI&?yA zQ20)|i3&Zijp+Rq&H+kvcHg~s+anLp=ks3P8*Dpm^jNqCk1E1p(`hI!F2Pc7wat5Q zuFaY`GZ?ZC1mBtgz-~9AvCy|U_s_M5=RIJ{7O%jh`~dH-w2$W82^EWoFoYLZZ2Q;-^(wFhAdxjMt+GddwZtk8dLAJ*dzG%&6+vewv?Q-a^is|B(#I8f+HZhe+U2>UoGxa5nsAbU{MDT9O7dshO70{tdj$Vi-RLkL2c(zZSrylvJSBzmYqy4 zK!(Nw{D@^C{r;kkIH#xL2abUcD$(hb7Zs1NbXe=Q`3 zIM(Dr1MP;%W9=Ao`kCopvr9(g+pvB;joj=wj&CLRA&(=j-ME1S#QREY^UUqe4TMQi zF&M)flaZ7pqJ4j=&N zYYRv#Hd&(D1gnV2v4e=OFP``n`|+Zm+swy)YD)6Nz~y&l=e zkv4>+btNGD^mybQsvarPSNP9JAC%!FARVH}GFtnu`>Ew)k3Ll3A78aqZy7Q00096M2+G; z>i2E2BTsMF6KrUSLc+GUq}Y}$UT6S<#j} z($Gw`#mg3ZpQ1Zn@YtzD`X)+o=KXU3h->YZTgP#Mo5YWlQ@V;W8Ympuy5&#V`0?Xx z+=Q!a&GMJ*;H%kI12x|W;E2r|hMPcdM4icm^-Li>O^a31Ml)PMh!foeWY>8MVnIST z0AxU$zvKF#xRpAo^>DX)YvSzmzO$B3;?aIk&O2*PTFyn+@~*Gi?T0zYKeFZYw`9jw2o2uJ zYh1)dAEftNwQ{-ZKV6W(7<4~3Zy?V%+riBnT>9G#67DkW5*yey)_Pq$*j~lRq)kRT zgk74QtT=`^5+F{nfebjcCer#GJX>MM%4)6r+-~aw4HpmhmjoA+%6?8oN|6LoESP?W zrQpx&1v0Yc#gqe@qmZOM;Ia>v(G@6hWMy02XQzU%hT5uQsn&Z)KN~jnTXuHf2X=J9 zQ?_{LN0u??9`rdaHV{YcnX~S-j+b0-BfjylZK)+R7ST<@h$q9avhrcf7?A7pT7o#w zBYEVFq~C3Qd~Q$x&^5Af+kx#EfAnR&6o9&zr2`-`{uV^If;^u7MyCi)Qw!QZuNOXG zTikL{b4iR9>Qk5Z3Z02NoQRllIdkPcahgbsK6IUJ!TiJ3aH(gzWIIW`$wqw90Kc?N zW&>O@nn+Vn2LYt)3~|sPO--qmj+ncLjFw`vsRyT}DdcTU7-2Mn?0A}fYA0|9z&WrW z-?rSh3BrXtu%;u2kFY-d23Qgt?vhdZ-h9&WW^e=;H<~D@a*w}mfM{`&>+X5$wZvVLFA8%mX%aL&s^FNfao;h*UM&(~^Z|}wjl1Xk9(V_5psk9HW zs)y^XlS_y=HMnBYcg-N_c(~Oj#Q0uV6W)Fvut&f;bIUgox1D=%50NiOvmRnjYcH$V zFmt4HC7E|DeMHtlJG_U-nuM(RPwVbWqgRLuq%R4%BdqJ^ZnHY}t&pBLfBgk0SV#|F z$i}nQ_?ur@)se#x0Q6JHQkX|DM^XZBU5%>fB@}LX(I%mI|M_fk>Qkb~pq?Xk>O}7c z&vTz^dQ{_&G{HAYM2GF|b0a!GUPteYB1a*_KYGxg{+s=yquN^jt25x6gwq9)zbmxWCeORHUZRoJ#GMXP>EqSd?WW{0D*ls`jcAA z6tIwToWr9n8O@a@3bP4{aK&?fu&bubuxq~jJ$nN^oEwa&b>7timr~zc%>jhl0}-xR zwaO+;nB-XwmMmKu*`w--kg3eq0hiPhfM2>~i9P!8gXjQ3dfKRZIiE6&@w|KdTunHx z!YSi1+5dt)zx+82bvSrcM=f^G2lOME_FC-7&Pwaqqq|+zv!A{C(K-h(ZF`Xt2Pfk= zEH2|y5Q74QVg*DMARDT?PMjdfyMg&Vei8r=phy{dwTmV9B2L3A(AptNz5a=xTj~Cd zh%J+?L#Hk__pv8!)xu|N)tXl0x z;_2VAb8s0=_;;m&$TC`LZRa1Jv#R|iHWdP4)ymc2Gr$0S(H!YNQRaSj1&Kg7LqHZK z=*L9Y2;OMUxSs|ZZ*USHpeaZxK|(^kodXdWesl^l(0{~W+zR4s=iURoe99>u%psWcSa$k7uvnW?sJ^M{t6(G}gO2p-O2Iu^3% zC1o5YQF{a2;&o5_*y`U|Xx9(w&fbQw0U7Gd2z(1?sRVqH&N+hzc*kM{*0JETw#ho# ztNSV;FxU~yn+&Pk?^eb~=#FK*DI_I5HC97NCJs9tto_4L;~rmhwxr(RJU8NFT0#EF z3dW;we$60u?}Ma2>WkXqvp%H_4e%w>LEQ>YGW}CE|MyS+QT51;pq8G|H+3L-C3r^T z4Xy{jKS6-O??3xD((a$VSBOrX`?DK=*1}))LMy`i52jaKnVUhgL)?*?`uZJw*XGdf z;gdtFfWhoO)->359252-Q_S^7I5GM5I9tbN6=IZyB!Rp98MPrUD^|)N>dC*%gX(g) zlR&1*c8~;6#OTvSk9x|B4oLR_mNxV%d#f@HQ|!T(cMnlah`}l9RXZ%X?u<1bMzpnO zGksAUP5h(qPbw^&Xj92ww**d4UGuXFPzf>vXk3Q5{%+g0al1`Hbh&)Z8o?GXa;HEm z<_KK}e>uKs4?Q%?w&xT6Z2KOweec&4$nV6^03(l&jaM+tox*| z5>-X|8k~*=SRe{&LGDQ!J2~4l&(cXWp$BS!ix$901gJ?r(#$*MCwKy%ti;p=8*zO< z3mq-7;xlK6fN}yu4zpPg&bBolmDtI{Br>J`0L;{f4Zqk9?b~jtx#+xx4Mlw1Y^z^- z-^%6Jm(-sAVtCU~3y@95*NfMoUF{=;m*9e3F|EOh0D zlS8OFBbrLdvD4@ulPv>IsRsS(Q8IR9^v<=CBm1nNTRRfe_O*A)h$zF^i%0;si_2zs$y>&)bDA@3r?!(1jz)L(JR=!6ysS#8^bW^_7;xd1>FdryT?#9jSyX z1lWuFjs=N{Sln3?vTk{o*!EW!SpmMJagvrGy3Fg|4rxItYUmDb{}mR3&^gn2V!Uz- zS-)e44MXI+bn#*)7}2T-S9W+ZK~WWZ*3Z1C7)lHJMMrw9>GpX~5Ru?I>-FUyvVT}7 zh^j{E?zLQk4HD7toRF^wgvpa8+Ku;r%?@vQ*Y|*oqDokct-JQ1i^Ldc?-|-j#Rv>; z5ya_9oYj~XLN;!Rt9~hRRUh2-gOBuw_FVPBWii(rA3kNF&3JW~}i7ICuj`7QSEGOc$o0UQuv5QCLs4r0Lp9sAnugL^?7T62tqm^US9m7iED zK77iAQHRlu)?PTMiO3=n$z6Q=w=5-e!VV)|5;9FhO!)KX3D~^gUm-9mU1v0b$UCc+ zt%@=P0rUcBCt$tWhz=~Cy(Xk4x=Up+M8aM;K)G-f49Z2%mkVLg7AB>eeQ>nWPP0G7 zDIGmk#(L17BsdcEilw~U+T_^ByAN39nR7OvTN^udc$Z})_2gYd$RXqT@JUl_(na%Z z=f)2$u~Uu}q0c+n(w2-Iot$HoND$NkCsbqodUUiTj8F2~x3@z$p`WA87?7%n$OaH= z9D3rA#sP%j%C=eqK*Ewvs-wV8~D#Jz**qtyxx@)yv+i%^|k)`Bk* zl?qv@uxDNAL1T{W`0ag&Jg1qGbVz!B!8qBV3f1|`BcG}o?S=aEw=9gNwfuWC5K!U4 zvIyB-$nE)eR;~qQ{1si(?ZZ7gI3FRhHg7?Ufk+Z0CMC4Q8%<)L0L0c%>YSjbZ$TfV zbTynj|5MZr->B#xlGyBZbyWcQRDdu@j&|JA55Oo1h8L&y*iIbGDnv|`h;o`in$p)a zp$}0;Z8_Q|WRQwQq7)rZ4p0j|K-z)YbSqb_u?HS_zn?i^SBY^%g7G|XT=S4tdLt(!f&S0C z_lKk~y4U8;n!`ovAFsAHO>OPccIf<0SEKvMhVmsgV=ay!_;m^K zdzN?rRT!co4(q@pa9QQ&%no7}UtL;lu@~QBsl#uychG?~=XbLFd86zI!KXK_T7m!A zF#GJFQ8sqUoi4J?-b=WwiT#zR03d}UK14wZYr(?Vj61$;cYg6|7c=F2{)<)xawY;P zKrVxT$>mn}J9Kd^=WODXNpQ_e{9FrX_-r#rn&TFQH({BF;0jQOrQ^m{w`w%p5C)@)viRSyyVgx&7^&(r0H_j+ z${jVtYl-OyPy`^d4>CcH*@%segs&u%v%a}K?ZDoBZi}PsAoKnf^jCs;@3??j!u^>#BuZ^23@kUUvn7T7kK`tdF0l;JW7VKxJj+Bea0Q%DyjjE*NGCy%Aq<}&+~n4i zf{r!t^$U}2gY!n)LPtA`_gHxKtB7dZ+sOM#z160p`yMh43<{rFQBmxpgk(?%+es=9 zseTg~TOEHwAwq<{-~1u2=xl-1W$CG~cYNcTZ$(C^Q3`o+!Hb@x@QD9Ke(K%2q@==n zw$besBqo=P354lbkILtt(-+_u06`q1TGzYu%j-nm&w=8Oie40bnP2#;{u6!cU-c#b zH#Z(dc+t7{?k&HxIZaBi?hXCw4Jn^Xn$VF_SeXAlEtm0Ie*hn1$?I<{o5S&R3m@pAQ zETO7%gEIGLh096&8JCK6m<}COygDVnK=&WQ+Hv-epS6EpveLeX4hO}DSO)6y2_SBk z8v?=KHgo1onvxy_Q*!{5 zj4@Z}+`SP1aWKl%A)mC45#^XF@5-sHVTfPvu9cV5P)1~(s zLhiaN?Hs76o<;0LonnGQ=f+q08g1GdnEngci%M|1K~U3IEY7ABPPQc=MP=`HQ8#zI zK%Cg|1NPdl|HZ!Z^{?C8i+*E8+xM{+tQljoUip@N-5B(+VFD!M;GD)zk&yznjIqo^ z7;e3h^_S5{h`tI4#R3GIL7++6Gcv{?cIr)E|E~RP@gnPiuU$cYz8fHD9}gLnk6v+r zT{3*6ZP~buM6=s5k0&WBvPW?Sx7~KLbGx2mi9Yllak2H>u+DbB@c}0IS%@CnShs7& zT1~xld(GCXTPHhpum&qkvMP`vp{C+EF)!ihx^%ZR5KlFGrLqBHg|VGs|0S~DvMUbT zF5+#5K-}%S=eqNG&z?Q)=#hi=#_R7`eMTk$u9dJDw+AFCZJ4qUqUUCa%8(o!#dSlF zN{7~j)pOUOqX^o))j}r^Fiyn!?DrJ*N<--hOOvh~>!^AW9L~Wtllm&jI&|x4Ut7G= z`a^uBaCRi7Yh-UHz+K0)-eL5+DflF=-?9mbJYsc#elilA6ERo}S7i{520g5CVSK>= z06+jqL_t)}j@ATqLJCG&3KgicoxnmMoVI~IJKH{jWoI;WuzlM%JMwZg#rny4-Qe&- z=@=?OeKkl&2|`v87bO@Z_@h6CFKcK}%p0Cb=}3ht?Oj26x1^+OWRMXA#MF?E+e4E8>A`+%k&;Yc%mlPT9MQp9(Dd zL@9FkeY0^WeFL%GTn4}`Exr?9P?d0@10EJJ(GgODCn6)pz4~d^Rz=jda^8(MXCIbE}FmCPA7D* zpYBbtUQfIP@*$dsleYL$p--+1)E;hR+;kN*~GukDH80c=0oCtmpbR z_J@msL|rp>i3nx=Hn3klsgp=XEBXM+**OWO0~1JqN4({x^}zD3(u$s22C`%QL{baL zgv;Ueu4mdvJJcn|4jw^f-Z{N>lbzaKL_G13?bwF+nLRdh_WkTYIwyc9M2JyK(dI4m9nrkpGkBl2 z(A2_PFp^qeG%2_(t_tM@Q{$5ZcOA@!n5!17tL=+l zwszewVtxVxlUNWHxoY7;X@I$m0lB7dem?rcZ|wGQqpb}((n0-ZI}+QucP}m#vG(S^ zQ}zK_;LCB-Q1Ahta8XZMTe0M{Lzj3VJQI7N0+$fW{~R65VZXEIrB@c`#e6zo0m&sG zacbPV6J_Gs^=sxmsm%Qx%^(6m<=k#6bo_*1AP^tBLR_CH4!{4 z3F<5^gX(Z?v20Lueuq=Kf$(zRzM#x_vcH zp2Xi2VjqI^#1Th|M^FJN|6$?J?VqO2u(@*{wqxsFV|?_p|48fJH{YXww8f}l_`n|a z(e9&m4i+zr4opHK88O7-8WOm6z%4`dS7If*DZWJVCdC_mNsd?kTN+51PC>RB$F};Nl2r* zQbT|g+t{X8?%D4I@S-))C4R~0RDJ7ImZA3=cLI1Jcwt7;^Jm-o@9?b zIf$9#gjTqC{%#lc#)29|!LXa} zrG1ToE;88n@S7V{v-)>jyhGo)=MF7fyo52seQo-JZv9$x%{5y7_~I}lA(X>UlW0#h zc|4u!-(RoFD=wnb#1s`{O&tLA^X{QK9jt3o1D4IcdMpA`P7+C3NH*o8xV11I+xJv! zM0*s>9}rPmtm;6O#wN#W+)ZCm4wh?be4pM}yGl5jRa7uKv?J=pLWzNX(uutl=22R% zFi*7ytMuj@ScG^qT;DT-hW2%U@Du-T<@r+(2&JROYTdfmkpIb=a$1_oN0z9)s$F&6 zFkD+-=730%UOxBRr;Ym@DrK7N3gvhHH)Hqn_d@#?dXZFX<^?_w#*9;Cm6ijnLU4M5 z=|U0%;Hj6`VgRh5fW?>=j-$*hds3UJwt{&Usv)`V?r56(b`g>obJkUwMAPEEeUz-T zh8UDgU!QYYm|2ms#DgXrP8bBena)}mFlfy}m8;tmIy*Be(I9cRe{@3T>yU0}{!|PrC|Jpn*|7ZK3jKGi^VQ3eB_BLq}Xvm83 zx*g_!{{#2viDgfO9O5v+5Q|~^rcGlU{MSdhj8LeJ2f+>rys&scpMCM%8G3E~OPV`l zmVSQc?d&}y86k~8e`nXD7idpMJAbiByud6#O`f(Gaj}G@1oODN9^M}>K?RPr1!TDn1yf_DFbF?(H za#^^5a$HLn2hG*%%ME5N@ITzNRo#o1>h?Roq5JN=pH+s|*m@AAc__fuQ>r^Cd39VT zr1t9w0%$+3&|ZW0CiX)zQ=BcyvCjI29 z?bbzU=?6s8gEb7sk@9a?r7%FdvFz$>vK9{)A5%V_u>pk&g3~Hi6qfpw%1R1#(?^eT zWLIBzjTS~N(&%wx*gb~ktXs8v(;n(+^7IIaB~L8V=H1`XLocsZcl9m}gPxjd4k2`N zp;N$I6k)Caa8lpgpn{?jH8Op%2!bodWGS989>B`ljZ*iAJssLkSBDIgy4hU6Ft$%` zz4tzHJ4;!`ldx7}u?+Kdn4W(xy@%@<=G%%ucf`$r5I6mGpvf`pSm-kbA<>81G$|uT z4UFZPvrZ+HnWeW5?&q3WK|c#?%)&jaA7X7NQzfU(Q(@&;k_;M^gq7#Gc^qqHOvPBJ z5fBZ@;|w6{0UGC;F}PO`#^mU|%!%5?@gY>mG}e z?=5up?7#v8gw!@-hcb(2lWU0L6eJ24@|q7DJ0gI+zjJhZT3c|L;_ZNzV|da9}$3UU0C^}p?ncRwgY9hj&XAFwd(0PX*gYypoWg-_Gy6#7p|Nr>U-@U+t z1pcylPD}tMh@ou|u4J^B6M}~TD;9Q+$K3kO+i9>#uo}U!nO;QSL7e2 z7^dbpRtOYZc5zMz%YDsz(XgL-@>ja|zWa5_KU@H_UO&i^yC*;OWLxu0+xWt1$qBj_sb(}I#k6R}`9 z9}CIWmeXQ`3zbB0pl2*fF9zHwBgbjjgz0*C-A0}8mHV~v!w=AoF(B!2mPQ<`dNtY| zKK*{4ZwXf5vT4)r{8IY`; zcPqt@D}l{ldf_}h{|qS&q#3+%&sP{)m=B7!2>YZd@xh*#Y+f6(OH9sr_F%m=32 z+CzyowBNuGc^-QJJ8b!-=A*-Vf-HC$1GW^pKI|plIl24@kBdkqFxW(hDcI)`ocl7i<-_)Zo zy{L6R{};{$Dz|i^a>^&FBo{@ey@4{FP3Rt=dvO6Wsa%Kikk{4j1Zv8JMdNa;Cxg3( z=ByKMxKSD8C+41XzJ9U#+z{hRp$f|0Z5zVeZ{EC_@^VYVD7oIIi$33T&pn`apVn4> z^JcyN&Ii7u0~_AfpXlIWSE>{E%kKVHz>E2i5sbcMxHfF>&|3)Ob{JwZv{&EMtg$9D z>T0H-j2Hwp!1Eplto5^7za{PeP}8rxT<3k_CT%|2M65Cu(9C*r(oDmSEXFGZP!0Zi zYIl-`0l?*0V>4^j-VYM~QMiokJqD2HU_+bUdTp&vo;_FP#l>o=1q@~&2Wv98{}B!@ zDBu`Xc1f8A4gyAM0yqQR*ly}TXg>wm$*9`F zS)<&e*I-B;@tWrz6L2pcZ>-V7&p)Ha^=qJUOU(gNM3$+O^VOlew9wHZ3Hq>W)x5$n zS;u1|O?%m$HR;%IKu0$}ngj3=<9bgVt_CH6Gs z2L*?}z7MD*@S^ZBeB))vgWw?uCC*HeDFteUw%nzpH-J^_YK1$&A7W4@J%@cPuwJY@ zZ$8}KjIjCmzuN4D@pb>**MGIg-@f(ze%yWk_Q=2e#7O-8ZXQGr`_Se(eohzQZ_$f(;5XBUure%%1H`iaM%U;!Cn3HvgG33JI`&yZtVT&O<)R;+~L zHemr+1G3w|?!0Z=cBrC!tQJ4^2y_WEMC*(+f3-Hwt{>f?gU4ph|2Fwt$b^R*GOM?V zdj#1DBFsJPQaF!6Go5{C!DwN<5NZ#LCEAEjFI-b%h`rg`VzGbZPK<&{gkD}ehg+}U z-(Bphe9KJ^@F z4HPlH`f4pFU(e`7!>essgh3*Zz7$u_d~yQa!))2o<&2rfkC$hIb2tJ1>V?QNm|#Q)=;ORg5kKtTv!+hmP?W zR0Kg=9mM??WlNa2s9jM`=&nyl*ZcJyD(s+Q%lKKeA!^t9s64Iz;E=BV)Gc~q=?Wcr z>bJOc`t^m&&IK^hrSIH%m(IK5DqVcd)p{32C6xKaLXHAd5XW=OzxoPN5uV_l7)!=C z2r{cNo&(PBo_UKFT&JavKOPhZ^D6_G2ALCU(pI2mjvuXqTi<2>4n6zW!@6w#1$u79 zN@Zb5q>-aJZd|Fh@85-0Wh(<~pV&=oupDtWF;1Z(3?~{yGdWHQM)thD=|64nBM@0F6f7_rU#HjIy$gN-GddWUR3|rp=h5J1Ni|EPW>T>iL)8)-2QF z#n0%f%Pt^R*At3GPb$p@VcQ{kv{UwMKzrMPRA3!gs8rE_xGQ_Co?iE|N{e#<6=f@r z=Di&#RaUabT(MAdr{Ayk)@H4IXN#Iq8k&=sAwV6e#5mJvtu&6FdR88D>6f>)s!=Vi z)TXq6KzYON3iRU&C9Qy<=3V^>#q51so8I_?MxA<|rW9AGvkq?n6=b?_9|on4v2nV= z0G9hZOP1h@IEbQwOO8`9yK^)nn;#7p!IY5PZTs$=8eG zoIy##%69$J*pgBr2k;RSi`N-m0pF;fKYSN>P$Y%Q!p>{S7MM3bP7L>IggCyP@SS(( zGVqu1G3-N4K8^avJC!hY28sr;Yj$X-|DZW!gimoS|GUPkk=QX?o^$p1J;yt^?#YWmAT5M>yNT$IT|4PaeYI}8?Y5!Ap|gno7Z5A6?x4ph@G2K*(dH zGXoQ+S9ToJm|3T*=oFaKBM+*rsX?cmdOGgid-UY<&oa-$lyu@~C3OR$L6D~RHskgl z&BzQOthOqybezi1yOQb|w!i?rpdjpD^|VUug~BY@whiIJ0|&;+b43&^?h#t~1QzVY z7hfEH|NYV@blDYGAYiZ5YX>%{a9DyeIulet%w+fWeI)Z!LYk6X=_AJwJL*%(h>@zL z@<=WDiUYX7jE-!^>Wc?)SBJok#v)B%5If@z5xxSiN*-M)akbh&M z3$fiRvAmoLQb7Uh8Plf(l<0|AsO#UyBF3E^hXOV!jpy006L<44)gRas60Ysek9CZR zRn<<8X$>hJah=o^ML5noF^}YV5RU-0-u`g2Ufp>_xd`LR@#RV*5q~8y+WNM3jVKtd zDWl7Dbk9MQv_ZZ8`dgtuwJms;A`1!Y+;EIRBhYLU)<-99)7ryT8aHBuO335eRaZr5 zmAEI4#(u`44=x>$uC|mMgDo6Q*N1$aF`*c1(z$OChQkV0)T}h}1Wr-tLD7iE!a9~( ztUV&0`D5hjnn7=N!oLZdb8Oi00P7%I>7V|#1Q5$r zRWOr+@V1o~VJWu75G=MxxgXcxG=4TTD*lK+SSPXU3nC%>Wrd;KhPBCc43TzC)j(U` zD+oVxH%oNiEB{*9Ss}MlhS)VC^9U`^V&g~9@+l2hK0ovPu3yR$u@qwo0}S&sbBxi) zK>%6NVhjB+Ev3R1d1F%YJKt~E{5Rb1N1y+LKR#w?`xv_q?fM`7{ks-;9%q}@#|@|V zsABO1hR>*4lk;Xh&KilW^eYx#sg3yCH*ML3TP{(TQz2prh`N5XdX7Z9Lbo*GFrx-{ z_~<}RP|DCmxm1x8Gb@0FPlQR_dfV-K;DHDJQkd9&e+xEiN7m?uVus;n_{T_5fA8N- zyp@wC>a_AwMN<*w$cv9i8(xg;iXaORGZ0njvromU=>-mMcrpt%5h2&nM%4*QRRsWv z89zE0!TvZFtE=pHQ*3#FxKI3q6O}NIY9n5}ESPvK7sRC6&}733!4(>d3#P9fBq_o@ z+5!$Yl5qD$1CFsGFzCeGF%$IQBQNOYAN-v5JpeomUp8of1Z1ixvwsWcZ`U_(`xbe8 z^zOU#QpOTdVSyM~BE0X#`dh4PueqMQx9i9oTN-`~l_fqJ;3Z4wrtsbSw0Yw;ZP~V0 z`+jqm_J!5Su4u<6Uw*Z60Xn=#f3&%GeU}EM$+V(L#o7T4i_lAsp(GVds^d69&~Ylt zo_Wk;;<;CZxdlceF2)7-{6cB8F?##hA@!%F>5^*}>Co{(y+*05cz_R6%SJ0dk=Wvi z)0LOluaT3=b+8+_`lu5r2Stt*Of-g^%)ZxGYtgkA>ygKP&iHYUSW!W7^78~&6#eza zSCF%{BhV6xKf^wt7qD`lc=iRoF#md;bb5uJzx$TZ=WYhd+sdb3md?43&gHq(s*F)V z@_-Hi)`=zI+r(*CH|8&So{X&%tRQxG?dVU&Dy}?Lr&IE)nvM)#`2NqxU*j3ZkHg)G z1`nfk0qrEL;LEPKSW8zd51$v2s&d~QcW{3(6osCTrFW?|z4MCRc=Rz+1jvOONm;XV zucW*i;FQu581I1I+;)hZ%XG!GG|9DR2K#X{GEW02YjM=LZ0<``71e^?`pt9dr^?M- za??(mbAfg>v}nZ|VtdS?`w>Q?T*X7zdC*T`S)ulIM(YsW*|`XU2jz|@J<2~Z!$xWQ z!9&U@tykWNVyt4^|F|j#NKY6vOcWX>5~ZUkBD21BpT>6V*O7NuBUC7E0NtfP|NZpJ zi%VebK-Uyeqh2)Y2YP5>tuT;`BPGkAvHni-=J1RJiwydWBYowpvP{kW%oPZ~c?e5s zBh`rB-mn!x0{!i(QacF9)MN^;BgCU=w-senq?K&$i;1F|5UB0;R$iC>~0AtA6XyXvbx^r)VsY_UBiqZv9(o-?W(^&k#{8xOMcqO(rXufF$y4s7~RKfL=k;-<@$NbX))(Fjd1$x_4718SxE zNEgaY9Ajy;VG=?v5e07mkdkTA)p>>`C2PhE(iRGev>!KQE6-nd^sv73rJHc!KSme# zg@CkfCpmp$n1iREenvOm{7-xs(6~zXw(1Po)Ll8ylwUvL=xRFIFq}zpy4O~pY zf`f++2CJ>Ur9}s^He(RZ@pu!)jvA@=DAr&_FB61k&EbPAm1vC|kxxvxOW(Nn9>!`A zWc`O~U|t5Pdees`54UC*&Wy5x3Zo2_(y|d~MYHw>*J@4DeFQ{kVx7V!ImJRO{ zzg&+8!ug7uD5JMS#}1LZ3Bs}&RI1NmuZb@{h^3YQU&+D+`|^WdQ_beLP{h`ggx{sf zXVcx|k{dLB4zbhI&sQgPKHGRE3lt~QJFLN?iYSGgt`9e`I~XPLPkgF#Z4q_|Ll>#H z<~!(^KZIdnXM4~tXIs57Skzqyuqbg?BP}BW&yQ*%@}9VXgW_uKnXpIp?2C2MXTGBB zvo2J^+zYUHvjNfIA@N#Z?S=eN^Gd(qhk<8Wih5%K8UUB(6r)uuxE{jU4DoLSS=f{B z%q+d}`_L9KQHMT7{`x+7h1>n;myf>s+xcz07^0w&GXDrStqIrh~z>mR@T zKlIkC{KjGn02PF6q%T-M)oiwt19^pNnrc*6TQfAw;U1$A(yLal)58z{8bHi47#vKU z`}J&i$E{m7YGQdA*2Zw{1cahS%95RUic+x@vM9q=k()||4%~mZd~N)@%@U8!m|G(@ zu9mzm7)lMj{XQVK>>!|)-l9n$J%_7yFjYm9r)eY!{8d{&R9V?5opAbTTKwc=SlHM= z!$*=XFc4gS$&^F8el|^IAO5kLn_881=EX{zd$p2II9DSko@SKd1d9A@SUstkD4-54Ye&Q9+s-f2-B{*V*ow3s+H1Z zQCSEenB3^(UKQaAt!^Tnf$?(O)>TL9d!s|A^FvrzEin3>@4u-YKsnZDjES*edH(rnrJ%8U$0s$lLHM6 zp+{alg4abAh5-^9q_<-Ng`=x`Df$e0a|%Z2tl=q|K9c6MT>o%9fR|$}DoSA;(t#m| zjPsVNeRSW*S7An~PMR`WwT#_cd#iNVeGXCFlA+0NfMoVKSZ>5)m0|3$23w)~US(h{ zSwU;Xnrz^CowpZaxiDepyT!x6&pBm=#sf?mKeJNh6Dts?Q)#Y16X5ZsnnAbt$rOOD zBvF6##A$)XkC%`pgWE5PiZ}zDV-N)^nO=R-&`=iDXX@WurDniDEe(`KBUyi7+#J2r zircrXpPq*CA-B|VaBQJa;l^yk@H7_?NW`-cho$IRz3n_tA8XBkBv)^;obsX^v;g9u z@Q362QA$lMDa6M+4{j$9?_J!Z+*!-Jy7$zaJ8I{%gYX%ZSE0H2#{pT1}Z$31eTv)gT`hMbK{lgo<~(|A;w-20K5W2#>Ddui|cRQ=e85NK5% z#fS%TM}nM#TR`AYIF=wFcU(LPywVeh3y?IO#@|H16Y(%QyO0uca+OjtTIpjaDrF=& zLKV{~eU(m(hQxScKV8;JVXh9eC$f+mHoQZsK|M!$5~v~`_uW81o8tGD@@5D_TMfG~q(o7iR^vcOPP+g~yG>=U$DAX}JJZ#yu zU#VHcG_@#~JTwYulOj-70#ir8XH7am(G{~5KcXD>R;p?@Z`2n)b+wi}_A51!ir{{D zgUp4sY{ze+u!x=iX~4iMtJVZ++qz>{h;weC3G5jsOw;2({efmo7^62 z?r^{si!@?*KCe8D!{zA?>yJG4h@QdCIXpL4ciehAog=ns3LPXWDboF$M<3DFb!*g2 zIAFvSigrUz30RclaP99sTC0OiB##q2oLQ2gp8BJ>mg$Gs)TTqdSk&aGefa7h^%Bj0 zyRe$(ojXshZMY*@C!05JrYcXT+KswoOvYi=+ACuuuH#(z;F)vEui=J_q95b*l5Dz` zkkg9W5lO3Klr%$>P(j5FlZji|YGPbt$yrOIAa)NlimrsPKoL871d9?M1j=X&F3eWI zTUq%wIPd}g_+hUV)Q*_g%b2MY(Se@Bq6jcgQ3yQ?FWvb9XqdmzORo0j0qn=Rv(nPX-&h33 zHP>9D#~y!#{lGIZd6P&Ijpn$`Fq8x{SB~vtf%LF&P#S}k?-7lKIoZugwL=KTt6RG4 z$}6=MX!_=@+X4|?M#Y6?2&y4VZb;Y-%}6LZ%?JM;a(Y;h7J7>o!Q}XE8P>~#4}2Hs z_+qYOY##Y$T+;xED6F!9P$q(3U>?zM;drc$7&K3jZ#F)U=AG^JO3lH_IdX)3AwAqn z1n(l3hrXPW(c`AC01#+79Ryt*wF$FvgALMTbdYKpcG<+!hb)oB?YzFI^pR>tu)4+3 zaT7aDN_)@*BN`|tMHsm(lDi#rGsZm@%4vD5oNQj8H#o;YQkjO$`;7L(2%@?7nEVqE zsx)rxvH(;-tG`g}Q{%zCfyuL?bSH|)GXO@exbzBsvqtPCjbP?dTj&t*C@9E#AGikw zd?)cs7zks-lm%va`)#)o@B6MEdGtx`+_RU%m?yJ@_yn!`<@a?HF1(+9>uahrQk6UDwR-xX~(MY`bukF8i=n6Q-Z0 z35?0MXO`-ZFLvtlSCYgF^Ib|}{-RHRK6H71uL~C(d1Z;9VTaS%p`V!2K4Otd9|3Vf zUaD-LW|$F>1~}bDW9$hRM5e-x;na7Us`av?!D{# zDupo(qP-h(UtL#C`WFloNPjX3`;pl35cEA7L7t?nbFWhquCPs5Q{DA7dS_d+UjO9} zrG4+}p1Z!TP3yM=0MR9s)qCNY-|3!j-G%#eSzu4|adBP>z{Qn_DiWip4_>ITv_>kJ zRHT;(taS~`(k6sm6W2HBp$FycXml>g>F=w&h%sfZ%A;FJF~Ox=R;Du+F2I}6qm}RP zrLHCn89It4?hwWOojhu|(lYYsnhujq%Tje0l~R~*7IdJsRxIxn{&UV-A@2MH+}0zq z(=`HMOAqndt6+NnxPI{ z&{51sV-$c6qk_2{B~@7K&@gMl&1_?!zn6)7zWnFks0@oSdek(XJpXejb2-oeske5pNtnjTYwSRl*XN^nTtNBHp-bb;W_9)xoE|$8+NjL!#Ch-bDS;4 z$V2*T^T|Oa1KMjoxJeCrKTs^8kXWwW)7?hgkpvVY*AbjvRhZC``{UZa_3&8!p3P?+ z+WfsY?k;TR%vQuAM{wXr-+uJwzx?O#Ti|)9v06O29?GD>Fkv9C+owtf;i=6QQEC5alaWfwQTWH&H@~n;Qn?j zkgcHiy!qNgR^5Zw-(=j`ilR}XQnOe{lucwwOoskF8@eJ??kbYeQCiE>yt z(}{)H4bn_r(aL3yN>sTwTt4LNeDZcBjGc)FZ!MRYga?h>uYf#bLB^m}hUbJ4MG@eq zCxmpuTxFedIu;bMM1+fDAx9{8*5z7~)~GY0D7|D|P?QKmbHEA-jD=@$t;t*N`H{Z- zyb?+24~@X+8Zsyl142y64xuvRqDU-&tIc3^7Fd%;!DH% z!{WpuI7a`pwZxC^yZg&@fw+@rgQ;zKO|e+C2X?L3Oj_wA;|hOm=N6TgS7LFXl@sS| z57j!zd&8Hux4nY|aa^^`QP!+;R1LlL!yqPKzL18k&8j-GH&~JjVD>*=vP{`CPgh#S z=~&PGWIJ|h%=j`TMYnLTaVm#Nrf{8po;{te8?S%sbGqS%8}Jr9MR)JbdgkSq5qQhk zcQ7Q%FIae`_HRbBXa2XWe^Zmj4A;f;FVw!RZ)(nEi?r^g6`@DoD_h?WmQLdEQY_B` zW#p7-+x|ny)l?X6FL{J1gcj3OLsta1)@c>Yj85h!f9fWc&Nx-~-}((Lpgi18X!&Z& z>{VjDxs=z`Z{I_%7KlW03k}dpLEBGeyqi9JLnlq2u0h!}N~-N;TONsr@( z9G=Y@Nyt+Q&rp;C0-5~GYstlo#!Z($wp_=^n`geZ-#Co2l#rN7WSD5aQzX*nr7t^zSq9g~c1z2hZwLkWa+9IiJ^1 zusjX!u;qv~ZZ`uj1LYzcI|U{d`DFFixqmhL0E8Xf$vHTog`A5?FrFbq05HkGl=_U3 z)C0xJG@{$G1!X$?wFYm7!f^(?_@>;Y-D1o|>8T~7WQ1Guey*|dDU{G=#ugVbK%OWB zu17v1Bz;mguQ^`fmbqQ~zryc)$Bl#?0w)eU+22JTDe}($h8_R%(P#D0{8u(#k=7C_9v=+WbL;AlTWkUIPdmWVdxOM1B!O zl;du+j+rn~(?Mk3_RV|3oH^ljK3%V`LM!%W3v9?$>CZ!g&+onYvxS`#-lxD&T$I_H zQKE~VULHY8G4sfeK-UqvfM}ywL|ARxAN>xN2tWw5z}XA0B|bN(7nl52k3IJs+G3v` zx#5fK%bjztCREpKv?fQ0Ef8l67McM(!#LOU{0wDMj;ggUNmYjrDG>;M7uE*B7{&xE zkVNA+?l%@@(21pDp*BbX>UcC?qaVA_8k2Ad*==OklM`7JC!Ru_(D`C4D#kjIvFu<0 z2KNxI;26f-bvXMFeny@JtusKb5qxDc)m%`i)lCVS@Qoj9n<3v=o0*{YnqGMUi?vxR zo?NbLY2x|`EVjiidd-3|Ke24IoWJv%x9h(9ze^#3Z^CdQbLPdgGHhu!uh4|{o|h&Gsl%W1vlZSMBHTCj_AT`Kc#o0 zvWO8C1qPmr;3$}WLQrum?3`Em*s`Z|;WgLm#l?>YHZl`8cLlXDJ&&%t=)&L6{Qf0f zj<2lw=Yc!QxT%)vy z810o0eph4AQ;xyxZU)JDVEx<7-+)e-HU$eB*CcMO4{0K6MCSrxe0SXTRqZ0pWWm*o zcwMJ=-+5hce*4})li8PCtLbN4KsByDjVLW8&ESo&-g+Zp%wPJn8qRd6%UUg$ww_u9q*cw1r8MsHIpyyr3s+DrQQLFGIxSG&K3qPeA zz%^}nOu8YW27Vhr0SvWmnG1&v+%3Tnl#wjEl9>~9_QL0(wP>x~1v<2JG;uq;j2#22 z@1o)nu}XVATwm1@Eu<=QV1fY;&D;KCHHs-J3c_Sa_ywkAmn8FROSs?4DnCY}5IV)e zv~6*MLl+MVznL)&y==ja0eMXo8%%Dhv~V7tIg0tV`aVGMfRLEabM&!RqOpjL9FAfA zrQofKqN-0Sm2i@=ep7M%c2G*J`FJz8LQbiHS6t763`ep>Yq)GEf^BKX|Dhl{3F@X> z-*ec*_r!e%OOS7ja`�-@Oma$oJ1?Bf`H$KKi$hzxj%Hef-`3`|XM1WW^;+Xh^DN zimm`=ZS89LQZ#1!#;oB$tT%t(H%U5duJUOV1@LzAf9 zzIDq6&Vg1Iv@4#64&<3I%%qHb77cksQM7l-N>nCp#bMy857z*xZ>dw)jt|sf6c`%3 zwZ@bgXXBkL3?+}8_7I0VD-EGKl6ciH$`8dH?@;6JEmAdBGg@=ZFg*XbE_;DQBNhXI zU;rWEh3B#I{q)0h%!K1vknMYSNr#T|8G%UAV!@Jcmj!wa2mYtX5a%k}G@ zd>_>0NafEwTP`8(LfvUt+VjeX>jh}Bu8C@=V=GC%Zq}sJ&(zq`QUEtynub-iZq3@z z^mg+W)0yoYlHeCzp$-tSYyS8$an~LdjvEtFR7&zPDP~-z!}|{4setK2QqeHC_|D@h z%*|6H=*Uo@00B`)JaHGbEO#BQ*1jXhwDgI`wd1w5ntR^adf}y)iM=%d!fMd!Rj=sF zU;d*0^~XQgg85hST7=>h51^(-v*(_mfBe!Hbn=W7RDJk}j?)Ry!O32^t;86 z>p5cg6VJI6cPoG<1auA1-%i%d0F2*&s6cZFWeyIk#mbnATR2ZJ7IZEC5w5|+SV*uI zkdR?sUCqW7Ufg)qCH)dnUgMdkOj13%cYUDly{u0&B?LdN8A=SEr^*GNSKN%VlvFW| z5Cj5~=l1=(@p7DF_707(HXI7EFtq?Ry`*(Dt6}SVy6TiE+Vt`Y?RxoHb!~bJVTJn_ zr22oabyHVki5)jp16iY}R54Pb=cDi@DBqt8BkwZ{6bIOCfS9~9Vl9Vl zF#p?T#^x_<2RaJq&EI|ejZ^-83p@vY19dqzLfmWY#7dn#?|d}iA46?+oiRkb#!j6< zp3`JKwRmx47Cds^pt(4hv9(X1$T?x)U9d>_$X7Rg<*PxvuB&nqGdbE0e#AM@OpO4rkDNn; zyz~jVz87D-nL6*MPM%IN;A=y2`(&)dv(GwHKl;%RG<8NL*B=1!hr5O2VomfG@(9Yb z++if=BBYx4E3IG^=Ib5jM&|Du8SUQ+*hjvYBliTP-+9zVxCxLLPzal*6(Ft-Ck z;2&GkFtyaeamqR83gw)?Kv5^3tN0nS)ta16Zd)3KwG(lL5rl`~q|u|W`nA=>D{0-s zB3E37cI-T&)LFAhi#SzvyN_{7<~%SeQ5tST7>fy5@tZ+$dN6FSdnh+zHBO)r>V!!X zaNTX^{KR{`o_TG+O?C5^Z_&Cx5Tvg=8Z73vz3X|-Kk0(gr|C~mKTX-MyxFe*HqF~T1b$dPZ8_)=&*2<9)B6BFb$HI zN5ppN+=*pc`O52RrJ(h+8@|f8pReOd**XJH!j#e?{qE_f^ygKpGy&ku_{rl#Qu|ii zuV>7eO^k1ocJJ7&O&d1>KDkbHRYyQQX3&!GuwomI>iwmUgj$U`g(EZ%^kwtW!?+$n z-}1mwxNO~Mrpqo~N@Df!Jnr!Ez<0hAI<;@yzDw6$_eln)U+0`PM>z#x5CnysW8 ze8hVFDYXCL`u9l@XwZ0`b1{nLZUlZUrNQa|s?3-FoqNeY z;6fd#;bo<`c;huJjr0d%zn#R}9B(r1dIg($?8bHeU6y;;VezFEjZxyL@v0*2O;!n6lNvB?-#mmi}bm> zzpMLy_*13h`|oaPVEmCHjJXxE;HrW%+kYRX#1;aQ^xpfZz_D~OS}I+zAwT;vsuu2vt>6V>>hmZ!2nQkZA1Tl%PqHr&$YGWWw9uH2B$F$ z)r5?-c7Z=WfvD7t>k2x{CNqqds`-*Xpf11i^#N^lh_f(x#pmiv0Fr z$z=kG9z}n&3E2oL7GKMe-3Xe^s@w7|_t(s#?o;YXXQ?kW4`GHy$89H|nI;W%0Wavn zJ=MXh3$P3YqFKatbMz+-BewZyqoFr7Z5KLHbXq!X|V8(&+?P4S%t z8}W+M?)|>HGK)c;j#AE97iiS!bCsK)Pkz*T?!QMyHckL)KA!rhTX$??L2*N9;GX1= z$^ZkLSTT-rTU#SB6y~C_rdD}b86aiH1Cm*<&LaoZyLYpicfL!3ZVXV6ZW~_uz1o`V zupCJRNl&IRX^M(r-p!5miXx|~0e4*w$@ydp2FQ7RQwyM#1Z7fTBq}9C@9sXLvgxO2 z?eo6_ToS8GPoJq{#NNh%AWofhl4>cR)l6+rTdT3vdzDF&{L;m^x_Ry`I}hq>KX?cW z<53DAkE7ecOr3Vtd3Y~y&mjb2={?tv8){^6fu35iOlepWsf8qFk0tJgianFg1U371 z14v>h8HWS}pW|Fz2s-Byx#Ft z+>3j#N{@k>Y$gf3nzV>cD{Kf)E47B`n+Am=kY}=f>ke zOSkUYp!S!R>e#!l5WaYu^;X4U002M$Nkl%Ecv|0yBt!i@|d1J-kCxN2IH1;~Pq>J)p}@n4m4MJd4Z!bPccWxcOkD|7Y&q*n)#9da<8vzlxSh4!2@Q5I?%4BqX-S&G8&&N zSp#!~c(Cgy;7%I{%5(A3C1C2G7`#Gu?RcxSGe# z9XrDUv##o;=tqQW>dQCYsNVsNFUrl)EHtnOzIm&@f8XtTYU!gqH#>RpS;)d@@_D}O zv{WF;QzJulEm|wCIDBIPaQ^dlf<|hQ6f(0|J zI9tOLD2bIasKf8BRO5?F)XCpInz$wwmICAE#4xT<_}2o-F($rq!RbMO57v4^UB>ZK zlu&t+l1`qd9xTBQ+RZdk60HquuM>gkEn=l|KL}?($2Jg=BbcXBEcydG5Aa;X7HrND zo7%c*1Mc5(0hr+?sgVT^IA!-vjjtGk1z4eN8v%jX?FlU$SifG=afOb|P1D}rKcU{H zqncDvs%RRbo>7#lMB4tewl^`_qT>9b|SSvvqxzp;FC1!jS81iZ$_ccynKObh(C@mEKoj7yT7$j zyAK_vSTikm0P>WTAFtX`#AC(YD3XUx%$fBZ8| zuAENJX}#v1!#u#4zj)&pHFf$7=$$&7#|{O-k2KQ^T#OC4xeqqftD0x;1Hqd_(SR%j zUJLFt*SefBGFMY`;x#2Zmag?BdX9#=6N!=M4=)O-DW&;X64d*wu4~Y-nmXLd^;jxc z)i7RzXzZ?zV}5c_#5!t@C<-@aBBwoTklIH0`ZixSRV{Y84?)sSf{x{q$c-$eTWR02sS+!)9s+N3|=EN+u;<9N6P|-Gs zcFE^9@p-!H zf83>CEnSXv)D(y-C`2qmyDly8hAcV@I={d6+G_(MbH$1kVIO~g(@i(&Y20KrH8o+r zEu6d=eQD80@hgZ45`uZVy34}(*Qknp*Q{Lyr3~l`H+}(>=`z(3w;Hk)vK^4HPw_zc2^X!Vy!_CmV zbBC&4U8Q5M{86({o2ex~{I*V=0zhCywtjTuXLWS*hn$~1tBlZcb9`?HR`u};3{Ze!0oTQb%dj_`{rL?M#C_j@@Zp=zX8uw1u z`*vKQ%?Rgadd+om&xm+BW*2GvXmTpMJ2mOlIcUejsNB&>l6JRdj>7d9-KLVFLiOa8 z>ChmJL}`NBg%U89(m4eg!}N!x&#R+kf-)w|R9|{NvAHg)j*O$xc80bds#ZVH{!Y9D z*)Y-(xKLmE-P6j!3jW}yKUEA?;JCarl@6zm;xVjzTwn2^YFn|aEKvGLygrVL?!Uq9-2*AP-1;m--^w{FZL;l{4pZzRkGoZO=&ZX)tQVkpKEB%C_M$gh37<2wMQQyz%;*y7;1t0Z_GT!+H|D z89#eJMvoj7+;zRU)jHX?AKEie{&-8h+8e5LGDuiN3VDY~09A<9;XN2cd9orpz`631 zqsR%Qb_;7{G>FjSba}8+d5keX+DJT_l#0Vm?a&ryMc~=9mH+ zQ`Y1YG!miHOx)St39?p$MHAeao>`8I3Ko`0inV0k0%v!=T_|^Gw6wW30?$G_C`KrF z#t8_dbv9$s`0C3#zJG%Ts&;5#r@a=Or*u4ShA{}dv(%MaqMnpIK$uv9?vBFxvFkAr z08Ssg&5|>j^^{D3?u_1c<@Gcvuj82J&%&$mB5_)JHGTu{&}Qc8*~L!;+V?-fi5p_# z@HwnTBR})5_=5UMDp9CLDw^xY=P`C3ALzrHwmU%Bh3hmS^ABSUV&N%C6zr~j6+YxP zV9Xag{mtef7~)%hVOD>$$N&7p-?_j;M?!;|z2F8l=Z#Tc7GMi1FGR73L)U2go~^Zc zQm87D84oH8Yo#Bz92^P4hDaEG$SN`~xJ4)3|65g$JXtMymC8JGfpX?vtl<}4r_{3- zXa_k~Ww?|MAKXV`cNK&TI*iG-AoI(cKYOzkcg7iK=%I%m`pa)dXig@P*VbJEF)~{O zR;bJfExK{)MXX5{OAJ<}VdAW1Vu;Jh=Z@D{g8e6=SucLV?o0pYr4J&lzDaZD&QViy zBi3X!VFa^)K~SVu1JJ3`tFOMI%h2qq>Z`S8-D~{TuS)v6`O4d<@#uTEwjL_AGcE>o z+;;CBdf|y*>vZ7zwFhlkWuaALSTB`11pcuC z?dEDGnY?b-R$>qbIfjK^R-v@fGqBEZ!*F~O0&-G9yQZ+ll8!fN_bTcx?gvD3a2th_ z%Ron_k>rjXOQ)DJ%-I&GQEwhA$4YupDoRI{sQLisx9d7*v{W`j`ExHV;DsIDXZtwYu?3|EwykAjhE~5XK@lR6eQ1ni-F^yk+Z_j}|65o4E4E z5epkVVZ3%(xRRsf7{v!`SL@NA{7_H+^FL{T+__9*MFr&Ujl!ZRBO{{&rrZV$zuT58 zv}nk89qu!`K-;O2`tD(J)KZ;)mZ5EbenxTidv)HVvAX-tyEOYEEl49G5nRRq_YH|*7n%F@-|0X5Vupo!e z0wG+Qry0fhxcGK}s)T+Rivg;a6co^3j;b^L{UADt6IFGRJJ?1njhwhD?sxH>-_$so z^d`d4RMv%lJpt>k=mJCxLLw(O$Eb8Ob`fSDZ*-sqHRZQXmTMeVLc^87w*N^31 zCX}H_Anc>aql?ZUmk!`c1A@H=3(;cZ*`pe z2rkw^?!!e8f|mm7aqmDEMqoe@><9pqolvmCY{5LiG=>0kxiBNfgOD*LbB_GD0p+wF zQr)9JprXo~8rX;T!N-jnr^z?nslF4>Q*3@Iu~rv)Wb0v-pk1cW9u|}`jXMb~wHzpS zp;RzlaWl`vvtR*8zAuv6<2i`MZhm8zbpYsaA4vKz21ddsf_%Llzu8+O<|BgFCE8hHP=oP*Q|2RE>K57*E{onwI!J=}s z{}d(#f`IVMAYC1N5F&{tAQKDpwrl768a#lu5A$;+{mAg!xk&yrZnMEz7wIVFkXosx z(3zO6P7*n5`x4ZYKutQDW4b#)(*~G6!QN;VY(!XaXFdT0;pFRrX{YGI>p!apzV#qP z0_UTT8I@{v)tCQ=7C-g8T41t9E{3a`7JRJl#6e;c0fan`D)Z-@Jx>q)A_yBEtmIQKi*KXG+gzM?*D=$`aZM9xs`6qq*t~+%v3~ws&BbP_o3hFU* zo-itmJ81)CQ2qAn#L?c->61q3jTe^a{MjdyY`sG-JpQOUHoY5^3tOj&rDHX$Yzi@l z1jS>;VTVF^Y5CPjc28et{0r4E-L0IF7FfT*afhN$#C;~-K zhUv6{XiSa4Wfy>E%~D@;Gs0~XWv3=-BAvju@(d;;)6sS+yG+9MHjR1NMy$^++ySn=2U@uC zrq62a>OX-3Y{UZIsNJhyCTYA_o3R9Q^RpOVT+CP)DU5;Lah<^E54Ciw1%^^f7xxa_ zS?8QKi;n5z)s1y@=0#U%V>MM_K-i{$5X~iqRG!?e(z1~nHjDTT6+vogmYYb4u~RF` zw1;~;)B-J%50;siqvOr>8k?Pg0z@<2tQ=f+QMz!>$!a>dPn}d}*+Joi`dR=YxN-|e zW~+SkNZieR>g+%`z)$;$IT?`C2kkq?mo}=5Ccg^JnMHD3T7!SCwjNNs=D_P6n0C(zd}xI0l=J7&L=a}>P}u7O7cVV8c^r7FMdQ%adSM|o3ERqE7}X--TDLB_-es9PKbfrU^F zpd5#SSbHHPWFgOHo|AyrXBd`c&6=0+-n8<&d0d3O1#6J^Ljuq9{{Ln(yZqmJvm4Jj zbVI_-rNR8(-vn#PPskUxXN*|%N7I>K3+Zdui*~abFo)?X0V1~maz83FDXTz^uSDbC z830C%YQj1F8>Ti4)T9L&1_9t}e(&4g4*vU)*o^<3Zd(NN`2|bHosoNudk$KWnLTWb zS+?>PsmQ`tFlUvYtZARWPfs2oq;li;lz!t6l=8)YQ8Mp0q)k-9%z4~s7Kc+0(6er! z2291zgR&g92~#Sx@cQdQS8_-Byoly6x>ie`T+F_aeR==@L=&`ktiZj~RxEo8*!Z=4 zj?zS|%ZV_gB_u;zqrC1aI+j1mvElswhm-IKk1ctUN;FsTDIz!>`?wkfA_{@DY{gO< zgWjtA&z+~VN1(Q`dY>BG&^TdPssbvmmQt7Shzg=gvNY~!{FptE?rP!iC{o!r1E0jKU) zP8XF<5?WQBNRsjPwMyLk2CmFE83W=kvDAo+$x=pSxS7XI;i3Mmgbn%b!}INi>Na12PtPW*94^w4PnI zoHARJHMMdQ9&s#T26P9O;4@1W>uwsm_5(K1wl}3cZ|l*oUaJSLKU=$Qy;gN!U#N_Y zf7Y~tdR;a_^dFlvKS% zxzwU`mya&!vJ*myP0dgpE;-YCV{1FPSn1kd)v6-$$x6si>wsPx0nQYc5z~fF4)5Ae z6W$Z_$_HDB*B#fa852~Ro2=2~<>gQ<=6Ll^fJXJoRHF(3gd{-N9awyg#EZHr=IURz z_UexVCHmq|9@ouxd>b-LL-6mx65dLW!6m^XvFO@`6lZ^4pS@Wyy?`+*2fDTEy`CPvTRBNW5dT$5ehiny$9#4FAqdqhL3Y8a6&edrV-O)=1p*Rzb(+gHb5(q1BMRCOmKNzV%vI zf{XZ#ClvMC3#y1YuIHY76wJXyRgkh|em7xq1*`_TAa`#st*A8dR9>e8JD;N-th?Hz zLYmkD086HxEJCoyd5NGry>x8N#hJG`KfxLxpChhJ1RwVh4S(?FygUoYu)$vmSn^%u zWfXeo(7=zdy6|F$$iDxDe_7GG>%Xx7|8l!pym|iJGtAo%(+?jkO}z0Z76um4jDpTY zwf)IDWA0gc=;uG>U`+3^v#9%6K_4-M8%!#6`whWcCIU?g>H}U(U&x(rYhW)f8LX8U z7Db>v%<%{Bzejie@L?rRou?LDNiJgRyrnp1+-t$6yj>(IF!|<bc!w*qn@l{039W`r-~GvQyfrn!%`Aey>3;odYt!Sf#!+#{f5#= ziRrrJrd##Pr~as(CW~%@?lUPLbmlxg`ioz3-z;VeT8;|(vEKwD!*PJNbv4QCQ((w0 zOg+GjPr_O`d)_&K4}Q#!YzC+Jp%J2!a3dK>=00xz>KbB>Q9Oqej>jV~D?#ZkdxA!} z04Chs-EPP!xI$h3(D6mPvrO#QEV_(-WjjgKK0+sPP<~jAiF`i;ROI%p>v1o0&(OBP z0d>_Rx$fVoOHP=i^|>i zy6O+KNV@q(P`bnbvD7{E&g;z2rlru7iByHz#N2ej6T0b|^u9j-xld~?z^AtAI_-V$ zO)9-qD;ogC<~Lr~$kH;VlVo6&JREAcfzghE^Y3p)m=cR?qABX>)99K|n8&62lwMj6 z93CZ(aZF>z$}^HwoCF17-E3`vLUHA%wH;IC*izzowYc7hsZJ=Tk;P&4!q`WREFtxg z6bq8H^K)}GhKf6d+1c8Gg_THbZS(3sb5E2H1Ge9Z_1euCVpN2p+3mO@T{AKxJxQPc z;>|o^Jl15M3UV^^$?N88&gpXlO&ufNy!Mq>^yZ)cpx0Ngq?J#u{`|^H?LBw^5F}Mu z($f&wgCI#qYWorLKv7uoib_FGr)%fly(%g$hK{3^nVqY#<>l%?m~Y)o;cQ&wF2

dmElM?RvWS0UX&zwHq~AzQk|Qn9MIVrN%5*E$|Vj7 zA{Hw@nRJ>SJVJ+Y+xFAa$9w}+4nn_EXN^eK$OL8=Iv-5S)lMqFw17ygLdWaF{b_;9 zA_#6_mkJx=V?lK^9}n(2Ru%8vsT?N3I)xsCYd*4eGO@~vQT+Bi^(gzpqwIZ18ll*E z6!fN8d<)hjD=hGsAnhB!GfY2w z=!aNzH>+UeSl#=>pXs7SpVaHy4+X_A(`$=@^vSd4C;`-IbU_*REZ4$w;4*Lntas1* zAp9d#g27O*QQ}y4G<0GfGDv(hmU3z~DF%oox(RbUxtI9FKxzJ-wF1ro9{O*aIZPOi zk9d~{$r~36+$VhaPyZP@>ObA_f6X13K)W27)PBap#+0|2;;g) zz=D~gD;Hj;JMO$a5D}vv{zgHtkW^sIl+ne&gBf^)Oq)r>Qran48#ENYWJV({f<$_Q zT}4vzcD1nJ!bDq&;j-$-ZO{$O-g#RlaOjPDWD;Sjo^)4e$My?^!4aCfU=i?XG-Kk1 zE&S~yH>k_5M*_@lY}rP>T{O%lAh!IV5RrwH{|;hR#g0Eoa~@c#74=z)I`i|2|MUaO zx#_zqyWw^{UrU>yGcIRA!1TEflaCjfVbmr&6Qs4T36m$$US?V7^My>){2La5@T69! zGupi&_+3dN3hU>Y<#aNqADh7eRv;?Im18L`MQ4^ixoClwKl)h6KkI=BxQfN5%{$p= z5<(6=IZW1INQCZ2s674bGgyF&=pyk1N3%b{wsz_eb_Xkz(eW5=+n~X9FX`OeSRGio zLAvY zw&snsv7EfQ0o<0CUwRpIWeuDhzxCUQojk2?ed9I_fN<5$5B1(Jf39RK!Fj`awfCPF zsrli%RNlB%mzK~sFQt=?1I<)qNmLDSzB+ovt*IT*>gEK!*Po}i>!Y>5zDGGQq%$%G zG%ttvSk0aQ(FeBxO?1=Lww9C#O1?4Aomgm9xGvr7HJPOECajuKWo022v-jvR<&G%P zVJx3@k3On%K}IIPtcv6Nls(X-1adcX2J3l|H<;p*RK03r&Rg>}810C%;a9Hnd+@jqF4^m+LDDyR- zHCTA=ZnB@>nql0boSjV*z&WgD=*Tff1Pkkbeu3I3gtmpx3?+vFehv{h>Q`R$jdJ(-mVE`EL`aPSDm} zq(32SDyD$0?M>IgE@H$g(1fdR)KiT*nr{qH zgEyMcKos%zICyTaEB8>3*I+l7B{N`5C?O6DMPcO;HN}%)pb%@*3<{d_7@0r$6_}?P zC>x^__!kfKU)~V6|9fu{SicD+@*Jiamk0}khKcOq2~`$8+QB(<*T9S)$BhyM1_!vq zfCFy>qDXMzX^+Pr5o5ZXQ7Y+2RgtKUhIbN;zg$Ob@QhWqCz7L#e;{lhwN z=Rm={j0)ofJWtU6SO_PcdpWIYGSxo{_k)Eg_t`~odKZgXBd5@b8}!?n=fmyAasEF0 z(s|NeyBn}Bvq%DM8djpMbR}2X2xW~MPsih2D*PYe7^6VBSDwL%_Le`keC_sJu;`jl z8}!mkFE*(Xvlx$S2$=fzox!>dbHR~YdA5Y>t`F|g?JU$vgyiH275c^<-%`coabb9N zY}v^f6q<`Z_xw}xE8He1GLP(nE6<~nNImr<*MnkRq}#v#6+Qpl^H}fz<=xOUY&|;o z#}$ehy^UB{1;VdT*?>Pb6CeBVEf@r`QzRpUPb(9IZ4AgT+P_l4q??59V&&3+^jD8B zSJzX|FwX2ZhotV}De57)J)XsB>nnxQN>RAMtkD}hkvejWa&CWs=LQ-<4bUSng&tg- z{nSVthGj75F7UYFOmj@AZvFMMy6o;B>$#_vVY=du1qik5spm8w_wk}@KB>jaA7x)! z0Bzr`%3V8k^(E)&ch5bGLe!-fAAK0~?UlOn(m8tinN@n@=g0JJT%WGH<*RyU%K>t| zaJeRuqX>f-M8HAM-^#mVV2%|`z=tfC=-RHAZQO^EH^2O9K`cJ@oDYfe~{`uS8Ld?G_Bw8 zHWqrkw!iM@ z6Jrufj3)M8Vl-xJOjl8Qv0#Y}0a2QC1{fHa-g{$uJHPb~x^u3*&-r%Fb)73;zE}Uu zzrN*ppJ&y3-3t&=uct~`I|CR7sembNU${V_&E@o8G;g3wYd3%7^i}jEH~H@RwS>{S zweLi(;*afD8DZMuPCuP0saA02IE+Hp0pYU)bv+s$9j1(&7}gV1SLA`h@E$@qmoSJ5 z3hPix2><V?yY;zTfBK`LZ=cu=HhUZ*GP!Ubg(g2xyJD%RL|rp&lRpXXH&webUN zgu+76S|7VE0BatWn?rfof;1r5P{hUN2MgPxALcC~pR5g!MMT^&j*PI~m{htzt@aYt zX=mMAlU9YKsmuc^I_|dvXkqS{;cr~Io|GJTqexx5p=l#b7y=dGvT38$aOi6&;`$-p zj-qDx56T#ujd$y=SJ$jn9Gz0?Jt9=p9jM7for*c7{K6(hOq#9+jJ-bYrPaPVmKj%I zwU2HXZr07j`uTbI!^MiMGODv)@}_RC;8H2=ad>c1jQ;$#zT^y-+06Bj$)SX(0;204 zz&=h|f{?I7l5O&t{eQQavirYnCKyc){tq|P2#@~{zx%)8*G#E!wI*flA3TTeTz5yY zFi8w>U~aXsn%l@d^Voyh1Ur3h?lEo#lgS3lEbWX5q-WCD1zn4|d9HX0-gr-z+_hR6 zD?teAYgP9dsCx2`a07cmL0-*|T_^%y%WJ+1$RX&m#ZF0s2aBm6VQ9+AnScl%vtYas zuB{Zz!W_&bM!6D}yq=tewaWQm!)8LOW95;MPQft=dd}Nw^UzEz4jP8CoC6Wibq->X zycP@8**NwU2+5v+Xf=hWsR^KqL8qOiL|H@+W7Nyy9i#-tb0*i@_W=#6Ec+nzy3O?$L_g#1WTyL*f zO$}Mo&^@u(G>TzFT7rtsoN;3Nqq0W=#F?R&|Klayb?-e|&BClF1m=b1k&&JPNaV!O z0yOwwYqjEo-E{SYQTpKZKWKDfxGtVFMsGg-B!z5ML!KZZpqQK~G$jpE7%0z~SxE{! z3pZ$W3B}f@R0DES2v1i~is2cP5HPfnVGab4D~a)eOR%+4t^k<2U|1O>x70?n%oYS% z2MPN=W5Vx22$ByQWbw8`w}sn;V2T0cGECuff2hi!BzXgLN*Xs&jb$Yo0O)h<)M=&C zPcLEQL=~Pc=JpOcih2x|cP9B1Ydq=#wc9a3Lu2uRG6?~n*!7hL8q0L(vk&zu=-9V^ z{3A*?d=U0A8cV@&By1qn9e}0i>d+5Bs}%)T1RYlkt&GlqsB9n)?2V8f9TTi9a&m*M z%uzy;E&Mg(#uZRZl0TkM2|yC+Q3GiIl;qK))NooDk;gI?|1&i9^#}@+KZWs|DVw?N zrsXQk%hSv;qtskpf#Jm(M7UF}215yXQ{oENd+#tYz9TiDH+O%F@_q-lmT-s4Y}1BK zI&k0s^>yKzHthmkd-;`kLT*|*_j_oU55#jYg%13Jg7ZF|u4z>v9;t=-Q(!kS zPphc0MQ6&(Swbjr!lR=>&>Fa=f_6++&^^eSbSDQKi@^|#k~9Tg1<0kU-yelYG=+QD z4{Erpo_(~|fz*Z}r@fth5-mUxHKN3t$jx`*y<2|Fi#3_-)uYk=FvU>LkXu?W&-e@- zqwifEtR{mfs2)5)!ve7MFg78f$H;aBIf~AZ)2>8Mtg)-1G_7;GxlCrWx*(H=$49B7 zwFO@s*}?gHhDFMA>Lqd?mg4|u`puv=i31w6AA`=7sFf9uhxbE}&{3+ywsLhJ+OFBu zFuwiDi*U?dr>LkfN|OGrE9q_#l$cJB$2tw8Cb@?mkKa^cJP!Ec$x))k@tP4TgS5r! zB?Rdl2hnK@)`-|GE#nAT)}QftI^G`Z*c)`aA0bLVYC3(o2_XZziXewwz3B}NenEZe zo{#kK?Mt-bo?BJVxmh1Q7ru+c8X6a~bdlp+G8@OR*CzMvx&8SkwtsVlXYvi7!#p0d zpsAO0`a0pQSmRSeHx5GIGX(Mo&?U>3tBpL*Hmf(Y&Bo5;FbXd)HIsZ*7PXpr>Z=8I z40}UwZJGL+=mSkva&M`ozNG-R_piwl)hT0GqOP26xvf`*_Qm8Jqz);PCZ5(MoY<1X zrtd{~!qADHC{91%`a#_I`UAT_Y1SYR+v$lnnq1;V@C~vbqyB;RCzt}&vxFoD@Zv0H z?kOQpQ_SukEfVFQ9Ln`G47hQI>-rIRdUYV2B&Uska&=zzzYHz?Y$85cJ zE&IMeQ8JV;WMw1#$BcY*ASI;F+r)@>8Aj>fd%Rp8LRq&e5v3l=i2~PK&ror z#mVHh-C?oX`QHBY%aGuTTCo6CoGR1Q<#(v0wpn|&Znp!V7){~ZDq%^Z;Ez+r@X!-a zDLOVztJZBmNj5v&rIye7=9{k_&(wZr{~4>t6^!wxpKaGjsG}AwvX0vik_SZ4lOx=; zaTALJ#3-KI3(r3blgxVVC0Ay7N(9e+Ke`Eqk=2A(7i#sJe|BoY#sV5SO4n-3tq$O2 zH-X}--un$SQlJ14Y*{S+QwR5I#~1Iauc6X8@35rd3QQo^$30B(?$JzmGNZi)_0@(I zYTodsx=$Qaz)Tou5Hf=Zs6LcSF#8YS96UN{!GvY&hmZ~&HC92RVWK(j5)%C3s-=J4 zS@K#|_tn0OIbpR>)Ctyy#%k(<<;rjGS7_=moh>g?E@;kd6x^_}6X0RxejwCyj~>$) z=4=kg&*OOjUJ&pFhYxBgO@;RqmV%&60?}Kq#NaxrjRTZ3a7)nN* zcY*TH6go!70L0xsD70R@fZ@YZHH;$VU%|88 zDVS0Yx-mH(t>wz2C=d_qLCACN)@U|>?}Ubt9zcnofW+E|e5x5<%_t5lP4PsV47LHb z0h#K7_uGWWS1~}>d%P20=2HTB#?K8&U*8sh&+HiodLGudMdSW zVwyhq-E&$tYpPNr0`^Xi}e zXGjwM(?9#);|DebgO)T4j8yE>pUDp^+=MV-C&C6y5-g`4;^yAmtS(~1b-j)H^3PA9 z2>qQ9m{C;?SY8D=6I4claA$#by!tr%AWVSpa>5PNxFG2rE{C7U@RRh(n}_>O z6q`wFA<7<$;n{?;JQtJ94LEcUiq9!TwR5n$ZLU1lTvm3v7Tt7%9(~}K3b=eJ0-x{* z$MZyq_hOl|LJ$z-ge7nslXP=pd7}i^*&~3tCt>R)%4*c58&m z0G^v*_CEWuF((L^b<3UF;gvxXOXBo&H`&O$0&r=h^!Ub7yBc)ixFU2m7A-#qu2)rb>@C0l%kp4gI~GMFqo2IANNwvlTFu`RUrx!_{3^pxi=2 zhuux8?yGllH)h#;0akLS_&otMU?Qzzj&A=(&82y2;Id+`TtuFaZrGf&EAz|R{Ft$3 z9U!{kG<3UiIpamRm2hfPY=S;&^-;u?H^V$rL+5Z5Z{AK6`a8O0`CS@w-5omo{=3YN zZmrp{QNMZqDeZ^<^W@1qyxikzS-VmXKK46(ig#W|XnNPFQcW2KL2_B8L(<&?f^`D9 zxNqwVRfTcZi8mU6GCYcRUxSAhf_G7K7WIfQn;H!*9C=Vz=2T;SDSy2Q=i0P3GHJSo zV^E$dt|mkptQgl0m69KgPR-EKk}3^LjHle8Ugf9GXy(1Q(@eJ)PS#>o?fF_Aeu?r* z8iB0D6UHzrV!x#)>*O1hu0#8dE4Hanv+=mSQBs~L7+Z(F>BmDpaT5pc+ULz$8fIrM>UH#NW@~Y*bQxU97Zwv^FPPtik zckbKV;c;p|S)otY{8`Ca4=b30?(Fm==E-3~z}a8~KoP``P~v5`>WhY8m9!%3(k^5? ztd$b;6Yts3nI=>{Fy?y6SsLks;UgT31mkAmmpZpGdWXoa@1A?#JpeOW*o=5kGMzm1`hEzYB%p4QPWg zvUW2zpceYeAyjtVysPx^y>~EqNVLW#6MDegGRbK<98)efp-`Y`4^5tPtzKWhiuVmP z!+dlU6rVFe^`EV6K9;yvBCHqpV{m*H{bF{Wo6Dic?=}vqmMpnN8zS(^NIhv zxv@YAo4FBg>qbQw3epuQv*kE^QIvs95Qn?c@YPsP)&_N*rQrVL$AH7>u(o3nN&V z)|!x>zw8$3Z7$Ha{qW)uO0`^-85u4fAg(&`UO~?}F&lJ}E$$vG$v{wyoR44!5qsp@ zd|=Jfl|~7~n>!BjB|TQ4z~Itu9{Hk0&25zb@))8-v8huU3(24EaQND)DddnvMJj*arBgpx~`jl1wyKh z`op76cY+7*yIb#m_?|Ye|C;NtMDfblP zg?SL%OD{0OeIZz<6XTPW66B?tjtW(Ox)GpIuqw$pdE>eJlB^$~iLO5(w0`ENJNLB* z!^?}j>)^0a2p3*+pBl&=xl(Hw>K(zHwMPucK|i}dZU9L@eOMaB_H{bF;sxCY)!Y3~ zzohne-c#ApLn2&0{J>=5qUy6i-w8ptA;7~kXmiE7aM*2JF>In^6-7BnLrH-~4-0|~ zs#f_0RT?*AwoaDUDg*$CQAD+Nwke&wSz=rwA=$$in*&M&9qI!0RtG{4yd)kaLKQGj zC)XZ4%mZ01n~GAiVFam=JwU4d0E|&C%~4cu-egceQqIegnf0s>Kzr>D|rm z>615zXgNmb(C&@L_5F9=1qip^83kK<|EcVTzTFNIpg%5>j)^o`K~`_y&NCS$q~I95i^g zW4)o=*;kKwx`aGt-TRa(!$)gP8D8h~Ws00evrYv38Jf|GPSDCniP<`4%nSrcoCN59 zpy~}AV89t@i>_XJo8DeWy%2ZPjWGvW=bn2;t5>bybo(8^%#tNbwPxjNPQtFC3H0O~ z)gJg<=VfK+gVnEV8X?tfrtHj6VT`*@?xE>ufEHXljg~riLKrC>B}W)mzSHe0U&2fN zJP!s$kQEc9^tc4Q@!IcH_aO=~eS~6e{v}~yU;HdC8{y$f=-M5lrn84RJ!`RC&%c7( z$y^?useQ1VbU}gU2O3g%jaVvr0b=YIKHaYS=UmAi@Yd=&l*F1C8IK26P8%OWRn2vc znuynAJp*gnAnYw~(G1EC_8&UT{0dZZe4PCKJn7_K1u%=SBp%PM29y{cMlC$119(}9 z(4I|Ci^C2C#KrqF)8kZBR;U2FYg?gvC+UO&azK+a@XqLz(M*rOn3OctgPsh9uQRX1 zTchEv_3dwPLV&x-^EJ{F&NF>HrXlkdub`Ql!0q*C72fNuC_p7C0iim0;9I%1H)_eE zrF!=9#~rWW#HoB|ZQiutYOUC`8s$Ul8+dT{=boSlf0#NO`w1t4M0E|OcC$(2!w7NK zwQ3BC?sRE|zTWXAVc79HT2`k%=2k1SsS0jW*wgUPT~r4uyVmi>2b4noFQ%Ig4H%qe zH%5W>4D*asSrJ}wr$rH1!{qyh1-L?Q*TF6K(Kp9SR0NW-x)&NR)}|>+D=;^BN)HjB z9(YF`&(v08g}_;Wu+x5XTmt`J9tD_ExuU|gwx}$_<;@wWobuQkH}1_ zhbWHi-)b~TQxfFz#-7H|wRH@@&5?~5t-W@gtS>un4-9N?!u&qmdtag*A&j3lvf$Y6 zchvgs3gz{e>5Uif*F(R!M^%81OjNUQohXbE5v*UchW*&`%_wUI%!2kI_H15;nJ12G z#~AbShNTPP@Y}1C))K}nX~Lb=#H<^D_I6`s`yfordZSDm!GcBZOOC@v%`8$T9y633 z@e=o8+5CB0_r@PNiB5%2zY0pGG)MR|We8ak=Hz?*Oq5`(`vH$uZT|h+{19o3V(B+z zsR!M#BLj67*!hw5U+|e9`?7Q9ID{A-N-8U9;9Rb{;YNLX@Gv!P05vE!wXmxn$@egr z68iD{jJ3f65^m%Q`ax>?ncBlcY-55NYW3M?o+cmmFz0WRm)+wPJFRQXgEP~LiJMS9`qcQFo}gKeDKx^0xWE9;BoSQn>KFLGfzK5 zU$%4|C4V;vLiF^?*EDg#BK4leipNvWf@$USwvU~0wE1Rvl#mX(Dv;C4f{eGV^q>N( z5%!%`aAAdDorAuEx7FViM2O|}2DIS`sg;?L*=6EBc z$VcZER;i+>kh-%N=le~7P`WYhhS4r752e)1x%m;MZH2Zg7h|u7oK_FHzd@P|CnUrp z?AqD?S*79)78d1`4^Mz-y-7vX51u#q0&398ovz-|@rfwN3cy6EdK!kApS|#k-u-$% z-f=C_+#v3hMHP(21QZ~X$u}xMALrN7!>?WA<70^=K;BLmcEf568LXpaH!O8f)_2UK zUm#<3d>~jyE1R4SC2=va08hNMZGW!jjEsdqoAR0XaDDjY2MWjIoPE(W?JueXCD=>Y z*@b)2r+OD!;NannNr=+PicWU6?X6JM z9vF?zrv> zoyt3=^zrl@bioiA3{nELa$Cz`>q!`^f_AcOgomxY6QW`WHHxh1=GfL$)&Zi}TBJ_S z7MeA`CMb^%q&S}?ZrPr2Xz3FD!XY^LS|f+YGX~w-z3EMU)1)X+%)x-cs;Q-QWz5VW zHC&<1r$zIx*LrgRoR!Bu`MY7mJ9>Zf`w$Uq;1zP4{r~sd|KkV${n!8DT@y=>|HJEl z!>0@t6gM8Uy@2!(uMEVKNkJPz=O$r&F`@dI7@k<<9s9ln!B@w~_X30%sTqWa{`mVp zI-Z5YpGjlF$ei=l3E-s{<>XGxz6*j_vvS;t#rJh~fRt=g%NA}5-L%bhuv)mq3l}?0 zFSl;p%1j7Rz>LN695q8d5yRCVnW=tyoef5$$|YtPO;3Z=P*tRsqvVNDJ`RyG6Deoh zSaK6U&42frkTf9rBBTf)$AKs`sH+rAoFXJr2^Y^)8ba)y*WVZtsJ39R3|+917hQRY zzTNz`y6DN)eP%z1(r=}Tle7#uCeMaawVydcNbWkg6KnM4mhH?dLbqWl(4t*JofMWP zxjt(TVxSHWX0XXN$6ugH z^KR9iHXk)bWT`PAM!v&yRN2u-yB7+53#~65;UE@~wIIn@a3lz=!2ke207*naREyea zE*X_QO}mbjX#(|Kd-l=R1r(_V1^~NctZc=xdt}Gsk3FLY9)1L3?K=JS^}p%XAKd1^ zxNVVJ0fsN$`KT<~0nr_SwM}gzO71t$=@CjOEOZ)5p>u3ZG!$#O?6Y6jQYH|D){h~K z_dYB$4Had0kRw1??qhyZgH~UQG19EjA#Tc~<-zg2+q7*h_YXydhr@}srqAv69$E{*f$n1 zgQq$wOVkO({1mwpKe|zPV8M5y@NDeDB4bcql(?L2Ry_*Llh9Qxja8c)>hV?(xIrQC zYjP}l<3)jX3`WRz5!N2y5$Q{An7OeVVA5&sV=>4H|B!G60#@h-1d@cp>jBil&nZVp zQf@ij3ILF$L{SI$)iyXYqZMd*O1!7+3ooWj0&1+7FjXJfLxW)-wO19(kNIb$QZ8Qp z&Rl8gBfJ`mQcXydcSx8D3X60VfR@q2hiTP{*R^ro8k+dlU|*4|+rCu+2hIx&lXd$ zpEaHV#Tbpj9OS2!`?PezSOXfj9wWJq1imS&AV6Igh7sQ8JZeZToIE?AO7h!Xgn0%US{%I@d7>QFcZR z=t{mU98gN87arxoZMt*zR5j#&t;r~!om)TCMYCq<7-8MG^DfoFRxj;8>#alG0Xj+T zA*`er-GEV0I#x&PNp!)=qx#V@HqQnz?tNIx#*u0{bz7?z#?6il1!z*LQS`(!()Pe$ zxOG^Ir(b+X58iQu{`|rdYON|&_Lz~nXxdbL_2pKLqQ~U1W5+mWu8~WwtE$uGmtEoT z_STXMwd1*?Sj`AFN5ZJsjN;Ig-q3?T7W#1(G0$zY=l}THdGmk$59<5hd$Z7%Sq_lW zAj>dQEF|D;TpI5WbaVpN#EQWRHcu^y9%3aYzg1e!7|?;&>fwhTw&eX9n#HX9usZr0<> z!W}^WEtkmF0~|M$);FHOd@amJu-v(CcGIuE{0ePev(^#JnNtve!?M-E@r>!+@@gKO z6ULwX&em(o7iI-no{Z}Sy=gnS`xf$fzk34IV8M{r=eSw@Sjt=%3HvTA_DgTPl@L;+ zKG?L5-!MSt%^}F5unxTtG#w!5Y-jykYajyCjSy-p!nKP9@XWK%Vuh_%Aw~A)4ZGoC z1tWaBFeLoAo^BR3iBq|fvvIs=z&2Loy?ps{{b|!?`p{*N%LBPZPq-eg+Zk`JyB`Fh zS-6;%9GbR52%t-s+@KFn7ps%DJ5AJD*`Zuc(5HP2N{{7${P>F=B`qyrcZ zo)*f(+wNrFnc3s<9{TmfBM<4x7k;Dre)$mRNrIj^@&UQQjT_g~?{J-#pzN%8_VB@d z8k3$vU%mYrlYw_{0?jrQa~ez@3nz_K?*469;oG!u=~BJ^0#s1usTQBmvA?f@sb-l% z8qQ!RG^%r6eZOe=Zbwe-pG>l^PuzrzB9FCLl|z zYcwe>o^-aKDhdh|jnYU0sc0RXZsOK-!2AG_tJ&)R79_LfEnP-a|3S;5C-fd-|YauFfJ`>WVBn|7~p1*dHI4t;I{+3R|C6^l}R}y z@iv#h6L^vjcg36ZB-a|lu{;`1gD&;b==2B`fBU7*15kJP=y9b^x=1CiVcOU1ro4hC z$i`z;3H?_qB}<0dc0=(RKEO(&48UceIP)4!^;&_21ybFpp9_UwwWWzQ6$SACWivh~ za6i1bsQxA;1KQbn<`@n@yY77SJ{9fTK?C9}ts;E6aNb<4TeBMKygYsQ!DhYt-X_+* zDRh(913J8)wE}3yNY<@kvjf!QxT^_sZg^*t^Dxw>W2BmZwhdAB{q~Q~zkl<8{lp~3 zzxDRrb-RE~ZI&#eM4nuDGxm<32SYEe3CoO+O z-nTuf;N|x#WYTPX@X||Jd1a# zYs*?)e#1N+CaiP#*kOLk;zZo}6G{ncs}{g{1+|n@%T}cbVEEzG(b#@11oPC>PiW;^ zD^vlCgE7GSpk!T8`tH>98Ox9h`3_HuhuYYaGv%zb4AkV?YpKt1#+&auiWzT)5U7Qd z>=v29VIf-!+}`!%3v@h({ei$*C+$e;=^#*M+?Z}*+_xb^qtg}-^j031F4vKOaXJ{7 zqre|LA-D4vYIg(sBlpBV21auLOS?{&D2b@S6HmNE5$*+Qr(ioDrWi+fF=0$VY})j$ zo&_OkIl*;n)@k`oH&ckeitkXHNlT|iOP4qibX%`C0J1nq$$)jd*npB;z4|RJ0Ci{r z&uYD91C}WJ^i7RR38kG-it=}E;ToB@7$*_*&70!crmMJ|u zjNw%BPSF*)YX9b4wV&Rvh{QAnlaC%CH0+JxaTb(vXj+O?TCBP~yHrq1t=U=2Py4B^ zq(=EA6o%7mHa0ev(DTASxzs- zHaD$0RH<)3mws>toNscrYKV}Oftd6sXL+FTw0!7FaJqXCb`x@7$w{C-8{`M=R$)o4 z64FNMR8ffnDQWoo%0KI8vnOe^d!t5pwyKSim@W*EW>0cv-U$w0=<6pNwSO>_@{Uk7 zV}Pz*vk8S}o`M*^WZgUWLM<9YTN-L53&_{)sq59olTF%NO#@jBsPKRwl^2%jL~XC? z-BEVr+^y~K=Y=q+;GOk>WK9h4g3uV{g7H*b->Ne;Evmyqww!(^o^f?$1!zpjm{AgL z6oUIQH(l^lYWVCd@@N1f%L=j`x5k#LDJ{Z>-8L8T2oe443xgKmhaZM3l8SZV1)(`9 z4`dZ9hr#&W<8-(s)8s{M!}ZPuMsoSqBIm#^+3sch+Q;Mdawq z_HdO&PSU|nLcL8WH6kILDd&J}Lg5)u&blWIA}@_E*gi4_6i<#3gz@Kt;Tjz{s3`X~ zT^cD}J3LG!C3)oW0Ow(+`8Afp>sqG~PDhBNG#y?Ejv?Ji64wPpKVh?}W0yi0#vV4wzS~UNn48Xo>0=^&fCZ7c^fJ9iVe5!2YM4fXjGMba zK7<)wT1!}M%p?>bRu6eU7cZL>mTO{4W0eu}V(v0YSyexI?gd4*6ybIGXywXP05gVa zN6cZeyI{3CRtnH%?k8tw`7z`m1`Fqk#&gGla}vRPI&a~85QRr|gq)lkg5ToweZDX= zu*ln4Y*r@GLoUvh=LT)*#zO6I7SGT%XQU^ibVopy_6+-^S!DuU1=7Y4N+BnL(huO+ z7H{_hNm$%g!Tu~?#&OIuWJ%pP|8nByuhX*%3w6Xq`0)Hm!1t@7x<%c{V_pHE%Ia?1JA9V)2?T z&&kfz1<4UQaq5KLU-bt06Hi!6$Oo@~PbxgBLwJA7<}Fm+whxHp~(eBL!=#t zk&&1-T-iZ{6g$h6_vw0dUNl=#acP9C=z>AfuNg%riqBv~4ZxH!j)UVxm^W^~CNnk= z%w@a2RatetQYMULuDNi}sX@hSnmB!m_U=2NQ)kMRk{mC~i&a!qsGt6M@u75$KpD3A z`QmwI={PlXy@bi?f$=w;t)+3RpUM&b4gHPeDG}Y|vj*^z4wh8w`U}TvUn%ArD8l)4X?|F|fBH3G-f|=`g>3hd(EBi6y+&Ei9{QN1WpuWz4A!f)j z4~c&|c|l7h`10F8t}mNr!r|0~jP&WycG4EpuAl2Pluici?3tdUGxUQ0wx&_#gZ`>P zX7oUK-pe|1yd`9jDbGIctBZMy2rBUGoI@YMlX^f`o(d-2Vqw<_F*NywNvE>0LViRT z{2KA+L2d>UWl2j;*0&$6*G==U9qRny(WVbqzK#So1Ioog(dI&o!0d94;UHK6S6Rr^ zCcI$`Y+DUs$5QUKMM>PuI51xp}+s-i~sE#-~IZ( z{qTSHH*G*2qku`%gQDm}P;?=T25k|a^Fka3P1r652%8v^>e@vMRFr>G8{S@_XCHY~ zPd@mFK6&p0z4hn6=;lR>X|9>>ge0tGj@5^lwL5^d=k9|q!2ylEzzyqb^{Neozfc?q zj+b8eHJ1LfdhD5}lnJwhc`L3cv_6FDAmLG0v(T7S)|uO#U3y~qj>;ONA3O<4^7>_( zJbnrtgg0?D2y(OQ+`54WBj5oESgjWSJ0S?O3WcZG&!jP^KP!gg59;QdZqeG6Z}Xa+ z6L0T@-?5i->mkl>HBL-JddM-MfJJvAh#l|OYW`SQzy9?zdIKSR5~blca-700T|hnG zjS9Z<#|oHzyFO_MQvBsV)S()V=Nir_a?ONg7S5le#?!f~{a_>Snc~C?MtNk9%2Mu$ zJh&t0s|nQXdORO1vbC^lB7By?b@{6Le6?!6Sfd6Wfu#o&(gLcH1$fPpMLL9sd&WYh zZPJ0>%SFghU?v^=iaB=rwQ=5*6RIr?@1UqQy0_j^&hRX~L$1)e(J#H>M)tvVP?Yt+!$BlMX2 zm0a-l($b>&tV12}A*OZaE4XNzVg@U<>*JMxL>NYk4`UPtK*N9LWpW#qsgkBnhr87q&#w5$aUFnWu7x_m9zuSFpgMh- zOBr#o$~#@C0Uv+GBqge(v(U!T)$o3 zXKSeGBgER_t4}KMdM>?1pW(rMa;g~KhKX9dDC{K1334-l#TUq&vknNp-d0E1ONVy& zMm=5CVf0=oPwTSc4uUk6as&flc`<2}wr`Kdfv24A-J*-b`W5feteX~H1MS)wg^#;P zNBTpRA2?iVi#l||En200tba-jdReR1;>-bpp_KaouK7?S=Z}FI#Pxb&4y z%}S@Z-VGkn_7cVR6e-iaUOu(O%A_E_m|XOz=m5n~yBSq=N?%h}@bR0k>2?g4U2p%D zdEBc^z+ai!8R#k2JF?cD2aq(a-Lw{u?HbmlVd}YdPNxq~cO?Kaqj}^Kxl|T~tu0<{ zShEq1)kTgm=!D3-a#ueR-^xnq-J$4np;ib7yg_%ca62+esScT*AP2DqQy7dqy_gpMEerjWuVx4OaYs>hjMX8V;WP57amJf-hS<) zzU!AixfR~RP#7gfX~xW%&>Gb_7V;o`h;ETd9E~slzq1?5l0c4nkb`Jb2FhcQMfUSM zZ`a1vE8(d;!Qh!yh=rC$FSyhkc=d?abA9GrI;}SdQABwIz25!_%C`*&@B&pyV1^RiIx_>N0SaHgXPYjWF-3t0k+o~ruuwb| zI(iaC%YiIrtZ2RyFxaKA?grIu*$A348ItP7dY-m4USnp+4NKju2+LvkA)NbaO4V&( zCPH-cZ(OEca%Dw9sj8yBtAp`$V$fK+E#!loFe8@xHIKZY8uu_AYjRT<^kBV&TTh=l zrrtB$2b-sieZr&*6_!0&UsCfo_WX-=fN*mKWhjPrH71fy7VyI_yrf?}_Bi~R6xIU< zs;$A>ZvT&!R?;`fVv2^LuyR5Jwe>$uMFBl!9XfZC36vC4T42 zZGb)cF^t*)LG_WRHjiZh@3_|$paeqA01#)}TB&b?xd%%g)-46bB+%`kMB~Se*I{yT zsQ?{L!o@l+W4Id2$qU9u!woyg=d@&si6Lr`j||5E!7HnyMy&;}AT%<LWLvPnj9O9OoPIW z^Xq~{z5#{S5t6KZ)iB7kyQ>y{&t?E~s4T}@HQ8t>1UC$ue&&M@mXFKA${QLhh#OkiKs#*0I=i7bDhd8Gq%n9 zHIizJP8}yQVt_GQJLU;m*OeT?|GCFV(R{xbp4!^tnw+=3+xfX~*vs!8_RXPfNKbtC z2_ye6-o86S`^)u`fpbpU2FujjP<$7q!TYw^YsVtsUxtQP2zji_^1nXDr{^xm0{JW| z$0c*T9)5w~pZ~cq$B~=!@_RCI918%`jmtV%$q@ zl{?|h;NAu;M_K&tzMpV>!crXhC`oz~RF6Ewd3e1h|J$A>!8euT5;h@>>9i6;sGId` zC}1P3zHZ6&y8qD!Rmnn3%NT*@=%woxFIU)vOSHBE2t3$x+y5Y5nll+#bmkGbFfnYh zJoD`HDmw6$mSE8iT;EOY*=C(09Aiq=fE*r_SoC7WQ8Vhy5g+o2U4)Qa2!G5@ovx9Y z@t_VL92z$kn+IVSH^Op8I@?RnI+m65Ll*>%El}ryka^^p7j)g6xy)jJu9byPVRaSt zQvKvc2v9;3be7+7t(14z9ktVb^09~YH|pnlPd94(6V#s(3hY9mTJE#}VHH0qSXE#$TXUX|AK!DtW((6Zn`LLf3^Z1?f_tbee(yf9T zuQf&7tMhME0SL|fc05-YH+rzxjhZcb!gN(&T$KCLMVw;b+%x%%nN1G70u=s;k)Ydh zbDhrhPd)Y=_s~NtS8db>u*Kv8Ot@~*b@aH)b;9TGuivD1KmJ%Bty-lx-%edKCQS{1 z2u9NV!l8y^K6e!!(WQa&pyMKR2926JiaDPkC4r6|krb(<#4v5yu}fdR_le?ezRQ91 zhX9)CY6pgnSJoC6gCZNy!MYaC(_6zwjn|H^cLMc~Qf5Si_I|Zh6J|`6cO;6Sib8zm zLx+tAW}W}wgIdCho(Nl4ytV_CFm;}fbV$(uC@Wv@*j=2|K?LVSHys{2L=HC)ttRiGScU(F~VU@;m?Jh(Y)~|X~ zOK!Y_wo=Em;SAJkgqF(*`vuW7)*rydd9?CLA6iU#MlYP2 z9jx7oHWY*#PB`|%zZIF%mWSYYt-aOALY>6$_GW|iIHRmC{){k zu9_&c@4{$emHH)fEP#28sd?{KqT~Qv@U#MmGP&|PhVXJY+@~E-vzcG5oVL}su6%1XvJGy`HEV47aGiwr*Q^HT@PR`JZerF3#0+_ao+I17pC8CB z6JKknqy6Y3Sdq-2<-4xTqak(|29nQhbLJB-?2?D{hDr3Hk1bkna+mm+^O>bJY(o_3 zaeMMF-<%V)6F0lWE|HDJWzWCALVN4n1rDjbb3Z~Lndf1(QXWj;0gzlUy&?#CkM{@h zh!)Ph0&c`A`1n3@gg-{QGq835QxKL&1rkik@J(|!jTlXK+XIuBEArL5e2=!{*Xcw$c&q2C%6Q=dR zON(S5K_ue`TWj?q3af~)(BTuOwP5+}T5#VZ@*OsYML~FoqFcw4VH|A{1QE&zrbu+! z2s|FF|M;*#rGdDshE0Fa`tF4%%azW|T__j}o03d&i~v8B-8iVD%BqTW+g*2R^}Cy? z%K}{)8Ye5%cS#01XDLf=B}pHIbO@reJq|5x~I?Mw>8?m<69DmK;oxgtwxY- zjpPcuQOf4cnQE*%u$vn1Qf^3>e)iL!(J_DmR`M$|@48=slcp;4!i#jOq8es(im$)i zqSoR-0it3Ph|P&t#%*E=iT8d~Qd34u-M zmV55g=ca5%W)Gb+_rt(c+2clO*364_;@~00hK0d~63GyCYWt4QblJ=qN&uah0dj8}3j9%M>{K6~+5`pLB_W#n-A2Xm(g znbHSdet3cPjdg0RuhpCjCaR|uPzb&8EC-$r;xq5i0r>~eVFC-!&vLQMBMa>t4BsFd z-FD6xc?ONQscObkJ-y{xJGwa@;Z_iWJs5U=Vc{w!f|8P+<^V<9j5@2eLCKN9@Miie z7XH%{1*ZX}(Fc!n@2#z%l;#XIff004e+#d0tm?=qm*c&RBcEzuiji=THZ;*D$S**p zc-6G4L$SImGa*L9L6im~;C(3%sBWc?9v)mL=>b1HvE)!XU~o>AeJIDXE`nPb52{Bw z;Z(YET{RS(AB0%C9S_$!o^)`oCciKxoph;>MSNgvi4F(WPu{x;E>1(cnlSf4(FJz4 zD4h-lW5ek9lM+TxJ=Q+^?_-U$L56V36Wti%47T~tm|`V&k!u{o z{j$2fq5R%CO=myl;k>dZJcjhfe}0aC<9uMC8C0mfV6*%1FWl^$OyinHch))2zthB= z=g?Kzz}RL&+cv)IJTotig<_j2FDEs{XBbI*g*W)j2GB|j7A;=POE;|Jl^l<$$Al%4 z&M$2r&MurnP-o9(Nj6vUK1Z=*f}(Ur3GauQuKS<)wKl%_dlelypii*qOu1!@$fVh6 z2Hn2r>UjVR2aXr$RV?n_eV?hx8i3-yJIAqPEsG*1XQYzm&USKYx83)GJV<_9O;k}) zkvXEO>v2&D>r>j#rgpOSo2sfysZGj8aZjPTK|{dDSFHpl@KEIf|&NX*H*J? zKa=;BizSqhE3j=3EI3m>4kVfos6DrE)h~Z>pUR2Lj~p{j*OE(Wq@7GtXu5WvB@AN& zYNO0ep=~X?lCUo!&|kj%AJhf4!Ok&Jm!gD^6S^s&rl*}YBJSi2dKn*AAo0Ce@m*M( z;}+kf;M0j3HY{4Nz0SD}8w*l0MQww4cGM;rSi;h+Mv!gHFAk!Tkmw^%JpkLuJ1RR> zE@e(vG5hWdk5(&QXcwMq2aCCWfZwxVhL0Vo1xx0`N&1k2FI@pO67PTLP}F_?K$k6?;|rf%t?C3^P3hn4-< z%UGd!h**u1*xrkmB0n4^Xukhg<@MvNnmcEWRB@swVaXyy&eb#~O{`t2E4 z1>N+#zU*c`B76nt$UH!gjB&bu-Dgb%Cm>d->n&;)*^@y zC;b7{Nr&~O03~;(Xk1n*(QiM!c*D;W^yt$HPfno&$XPx9(7jrA(@hkJ;|U^^ubLDH z$rJg=zirT#imBZaR0NK0cxQy@Ci~%drv9)WF1+&~+08O(ckj)z-li->M+Uk^+>Z?VgLY(@&g1tvIeextooWp3L(@gZ^7RL)V zqV453-lU_z;4hv&S%;78RNC0{bfk)|5#H9{4Is?va^=Lp#F7{(zX(d{@q))E#Hx~#a9EL7__*V}g4czt2Gta=) z`T)iVobwo(uGDz8b3aV+SoqqM%-gTOO{=RVT2G3?1HhOWV_g_Le!-C_vLTskbJikN zYsux!ziuHVPaF7v-*f*BIqFHc+HepKfY7E0^V@mO=N9(mh|V$XxVE(Hw+35uHk0ef zZ;MlX|C%TNQiV5kCg;wX6SQ-*$M@U07bbp*Abh`l|C9@Ix&fcNC{vuKF`OhVFN`!f z8v&F>?D+8~pLTw4uJ8A*F$0BLNF)*q%R->G1FTmYa1X3f>wCsLb@U>!EUcWxDm%DG z<;RaOa3oF9vgRA+L2{gT+z^&r3wL4M*lhiD?sZOab@roo>o|Fp^($99pC5s<@h=b2 zLHO#c5pZFe_S8xi5!NINAe|7XS-_E8Y_M05imPg!+O`4O&lEoWOHKiShXA|fnMako zd$+D(LWM)~Ww{a>(WsdADD?y6Gysd#qqzMD^|=#XY^*54Y3ic>&sFj9A)1Uwy45E{ z@#8MknWkp_<_(k)-d4mVa}lPK$p9Fll#nR7(E)NeW(@`ggsY^X1y3?xF%&NMbwFK} zIR+?rh;|%3!{URs3A??g8^&~Il{|R?aK4(nqP4TUQ|0{>)}rK` z$$d___H&H$7B3^dnGXCM&j?;b#ideDHk^=6s9LDUY9piv082o$zjhu5c2IJJ20199 z%cWYeo`r&k+(FaGdJkag?x9YRvDGlS_>zM|KnS4A!Ugm7Hw16!r1O+^`3>Y)z17Nm z@$w1MCtE-I-Y|LWxu^8POTS@pVUB?^@~42-Cp1hK;b}bit9v*u#l`H>g}h!x(P5sr zYcwIA6D8%ke%TFrd&TSQ%RIvlwPBpJ;3bBD_-!H-6i&{=VEiwmKPdO=G;f_34&RIM-^0wiKg?!=S1gPzA== zu>){7CXdIC@z(SA-=(WAo2gdrT^MNsRh`i36?-%aw5dDe-q=O%Gcv&eRoVT4eT|ws zf_->0#2es}2;iOralm+L#dfJae98&+Wyh1Jss)fkWa3y^F>92Z7{-zpQ2iJ>0HjVG zgExOvqtY|sZ2a6|2AV*$Wz^^~Fe)8_k$<#~9X>>Br7Zn*%}QN-(=RDdr_pN-pcO)} zM?s5*qcF0pIKJjI&1C&Sqx$JsE%b4mXFZ|M62kYj+ygVRom_D+9z6NW{p1`QP*8zk zF)*$qI(30&eD~qW`ZGo$EQ|oUpnIYO%SuY*4;prWK5<~J=-=0`EW(cCEw={lzz85( zNeLV%ZPg))vulVJ^!nmm5)ZWQ4%TX{9})sf$M_<*LcFQd1w58YWTU;RMCkyL+Tjch zC0AQpR-h4yv5qpR#sIN&z=`}~+f2rPxAEK@tjE85{jd0I6T*~+wnbGdCd?t}p=2)k|DwoN;> zZ`YbtZ>xro&(fuf$){xLPR=J6I;zr|1`Q^YV;Fgn>S4#QuEF`RSClq3qre8#fK?e! z@;C)+FVnYQ7mP|$UDzHkEFi7K^a&3cuQv@Q)yQK@?{{mu}ku&)FKfwT$?03sbC zUj%Yz-dC!B^Ck7~`&=HBBwUo4te1ZCqHY0nG5nG_x{RFR*cr1GmN62d8Wb5`iscs? zPM=mN;V)0ZsG-#9h4{Mg*B=7l1l1BA>Llz`Qdz6=CKCP_4gGkog9u7D&}&{84aP)2 zDj`hy`GxdKYp3=Kj>h&uMW$z|s1^`_<f?LgDg@q=YK&Tc{x7BfEFH@&OfBExY_3G~l2_oFAc)Wqf71zws=D)tGniIK-%S_X# z;c5D2?FMxbs-3goN*&qyv2LG#wO;(y{c?|p)HuRw-pti7P`SQ%an()5S`IJd%TGM3 zunXsC5Tv3jA*vv9j!j=~(iK?Sz8O;hCqz?|8IEV$}DYf2CxAA z+QA)LX_h-rE8clufy2kj3!?5pJjyROzoT*Fwm#glM+ye*Jf^BG^MU z{ets##pRdl(7{}qznXLun^pDhY9&uQpWK=?Lv>f~pI#(#Qm%oTBF*RCeY5J1I-9#wcg~xQ!~F&X z)uGg(VW6?ztUE|I%AgCw&kc{zvRwm21ln1L4K!k|??Yh_DYU;4aVeA|WB0he$+V{J3nqIqDK4VJHG%bK>Apje~UJ;E{uLY){aGKe$~5lsot_M$P19 zyLnVr)F?YFKq-X$PnQ-eYIqhronWjGsQb-0RvpAe$iH z#^-Suu#MGtf!rf6(h`BBS%xR$(X&n~Ybj{K%?ZPJ4d`gl#0YPl5C3JF54IV(!%|pW zb~VskprngDzMq;2i+2%H?Idd9VU33&dI-dr3MbN$;?}0=$w5kl%4>8G;4S865S~;Z zbKeJJ$8yze7*a72+@n1^owi6u1!&#aWAI{&%PJI+Og@x+bxA?K;vn1hXWef*Rq1$5 zv$9e&njG!wRckeW-U3HP9zAnLaieo|_02!h>i0j_C+jxrmrwszAMU~Ui%g+jCYid< zI{omGr}X*0gS?kW;bkgoB?|k9b7d}_w$QgZ8OU8D`RJxh#9Bd}aJYpTW8|pGaf|p_ zAIw~G+0JINABEts)7Z~#GjZ;`&lA%d=X3@V$@#8*#Ze;s&OUwIUjOU1A$9hjXJ%(_ zo4s%U4*mDNYig(LeDt5+8*+geB+Cu-nM;OnWT1Zi3_a4Y4vab9eq(zY8e%L+gtR$y zc+}2c$6R26**DB`ux-ei;8#r8zx?e@{rCqzV8r;5S;Htf>ln`Zbd=-JsPmkU?HINT zy9d@n#gy%qEn5^puHh&*`in2V)Q!u3s0d)~XJEmvas$CeNM{f$sFQ_cJc(_1WUZjb z>MP3S2V(5=KhwKv(N&s#$uth%r?HpJQY#CgK0Hh1g#20%+P0AD8=>7I4A6viH!>+! zGe@T=8^Yk3Q^x8x@|eE>N!1A=tbfcUI@;>0BNQDQswb>pE628k&q3Ch7(r7f@7gI7UZEAy&TeDJFY3R&=kNp z5y?*NR3l2VqLRk9gk1(<&Tz-$@gnUWz-te37a1u@^wO)Lqjjmu$;Daz#5!^}g8FlF zkUkg{{05dq`NL!%LHMPixlLJPC+qyn=g2K8$)UQkW}H@c=Rv>0vE&|q_~TnaHd1sR z8jXQ*zQS^*snP|?C+|Q6sSo)MVEi=gOdl4D^_#7ge|iH?GExE4uYl4l%7M%G^SwS` z=-vCa>cJ-;*2}N`3D3h_qZZsO0kUwxO70=gRlEc5r=e0m{n;H@v>zyv4$-cRmnR{~ zF@R83zVea=nj1BJ)=bsoG4Fe0rMjWaYNOM@735XlhnTtzW|VPIqn#ix+tXC9?8FG} z1rwEV{_@M6iUyI|hvjU{_pN{ryrBEK+db%az~INul}xh35%+;ni1k``veg zfueUHo<_b?#sto1rO-X{gQZZiL*=G}I z=ePiOjR=B78}^cPxHnVD=Xnr~X=4qaYV0H|+N->FSJh(#4?v!7+?Li~F2s$s=SN9` zSD#V>y)`{65nxM$lJM?A2vtWi#{zsX3duiq5`hVijnf{$O>v-Y2Rqt8Lq~x#3t}C& zX?O}s>EuaO!{*`_iZ@8ev59W%4v-ICwCrZW*XjD>Yp=@> zM0U8%>8M2QIZXrR)KN}ocG|TI)t!{3sPm>PZVcgT7cb>pc%l4LVbRGxpGL=%b>Qo5 zx?}k=eY9b%BS($G(B$Y?j1UV!9zT8pd5ml}Wrz?pO0wsF{XAh$zW?3E`zE`c;1GX@ zgza}9nnX6IW=PuG$Ij>HKK|D$ymOk_Q8Y}K?=`h^-lml769lTGLG0v*F38*|d&|x7 z5-hZ7gJfR=_K#b(cpopl|ByQJEg(0zD2Mk&-yh_au=P6vX!n_QI}g05iwpLEBM zmTBI#SCVXR(!rC33LQR9jeaRC<|u$7#&%9DoqSFMmTxs-mr|0?2ey5oJ)iyEL0GlH zZ1Iyj?@-9tsXFEwsY+0Wy?#;D3=OInFVsf<86D`uUOR0hG0BpK+i2Ad`go3JRGHPCPCJJ~= zN{pfr20nyZ!)b+7lXphzCLDjc2NfcWWSEZc zKLA^Zr^Y8m=mHeQUmpCGl5@twHHm@)td$(Vc&9|mxLwOIa9k<1FhbxyJlU(SxmKsU zJXAt)a_J!an_S~CAoUp&rs#{#NENup(ZQ;k!fI;o7=u8H$~*D2UVnR)Zo6TLR-fndaB}+Tra7}|vb#?eyT69p^-?_ELo~wpmPIkByMO)@ zz5MdaETDePy!28!)>rBzDCKwr|J32}+V$3JloVkQP>BE4AAf@)zDUJ~b}P!)lhR6* zHcH;sp3&G1k~?Z+4Yr`PN}(IetD%TIFdQT`HIg7|`!FC|qcXI+vRzGtB9G-4C<`FY z`=EtatzJ2_NLe#J7%YLqCxWu|!zdt6#Qm;n>jWf1w21P9p0j7k<M#N?nEL41*Mg$_lf5_0IrG%`<}_u_?#?g-wrx5 z)Pu;HU5;oActFe&7vz zW)k}Q&v^2$Re1k!wss=+(m6dlQ%C!pd&iWbZT6DM?J$%$@1b-ImX4J$h!y2*SZ8S@ zl`oxfp??3`ADycwO#V)=XmDo4_Oy{&d^x$_4>sNsj;ip z)-Sg?pSfGI7{Ou9V;Oztkha_JPuJdYUXv{(q+)v+HDZLWgKzVJhaYyX&l<+s4+e>O z2h3i`!m?|!i(}tVp$%fenj$sEnE#8p_l~cty3)Uwu6pmicgvRL-ocF)z;rM+H6)WB zlF6hJN=PLnlR8Nz%p{>hC}BcPp%{z}7~>{ewz_2X-gVXP)%|^+Ejw?1pZEQHcn@4l zy5-z`_St*YXFV&N=VPXZZRdH*?U7&HN1axW^|N`#2gj`+WffVn-tps25pJ2sid6yr zEa9~oJQ9&VheQ8U6a(!m*YF=d{Sg#ckHV5p{CvfBmkXLkLC$eaenL-ED0x3#&nz@l zHE;gaQmK23#mYTe*Jv5#O9|Tni4M@E8&udlpp+Sc`7;#L5A_m`0|C}ve;i?)XnBMt zJyEd6r{-8KO+`nji%{69y`!B3c`Kix2ptq(Qd|smWR;dds5Fu>biwpd-_d8ycy}W} zAp;;1Ra>>FViDFhHI|fBBmj!3D9j-*(Ph0uum%?UpUu4a=OvtLZ)(9 zHos{57Mxc?f;5&LnVh6X4YFY7>w#bX%zkj+eU9N{`{PT|d;A@2JCs+@W z%+YZ=OI)^fvt7LH9DDMar>z3eObTJsx88cw?U&uVcG{lT{*E!#ZD0BPC+)e%e$QHJ zx37NUR{QHy58D7uO1G?AW(Qt-#kw0$+D7WWj=cI8y1bWKFLjv-gwI1UK;`-Qn8SJY z+wdqXBkYl(Ny;#ylWi)c407i%$j49jaEgy+VYGz03WHWSKc=^1mbzh7U6MaVzA{vv6i2iX6bnA&CMtk z4B#BXyYfOtQFK0tsn1bR>`OucbZ_umE@_NK z@j+HZs(J$ewUF^X2(0N77!w4EH4zdbSwTceq-4b$qXP4c+yXn+(gImK>k?zPe~{vO zygT(i%*K!lqm#Xi!#KR$2}&#!(jB7BQ!S|GDhy6x22S>QZG^57t4eb12szKNqAF_s zNUh-Qb$btzn6Cf;KmbWZK~$NW+$A4;Kol%Jwb&7cQ-nM$XVACqw_vWj}U?zzBCi$y+;fl&C=jAPU4GXeeq3P`x z@36gl-(lS#^Z8q8gn#G)rx+C3<2d7ONIfW7rvLu=IHM*0`KkZy-=%I8u+YCcP$c@p z9SdHZbdwHEs$=&@n7fu5x)>=6V*ZXmSyzMQa={HBwMU+QSZBf#kU^-sA@DChq-=1Z z&who1pYC9Wl(&-(!_mTP1ELK4y|S{>zWL2>qP!sD;id$$NM&8qmNVjuFO@#1Bd?y{%{UO3eQ~Tr2!}zi6l>3a}dsdYeQEVS(zxw7^ zg}213A>4VKg-kex9mB~8En+eIN&W{D@|r=oGZD679ReMyq!;Q>+js~}_YDJtT>%%6 z%+`1LRXB~eJjH;*n7b(~-4VJYtW3$Ww@K@3;<@1dsmQG4hSd6$|>^* zA@tMJ++?W{F*Y_fjvd8$vI>EoXCfd0FSYepE|)uq@Q=V#%uPt5xE*VL1c*2N-NMPM z#6hAP3Ec`vz!czv(hM$GW=+(3 zO|WLXgr+|8jW61RAmZ|G{hD=yIP`>Pu;w1J^PyfFJl$^5xsW*1*`OC;`WPUem1`&` z>4O?CmarrDsrK0WFu5GG^7WV6do?w7!{+7agh_jmbz5FhLP*nZAKiVO{TJvw?YYOF zc-VgMy>Ig?o!yTf2LVl3^u}9l>Eh*f`4yMji!Z%wk3aq-)P0LEvL3VRuH8uq&PhBP z6ce&ZD_FV2dw{r0Dd3NBE>aSBZb}0HhQ2AZK7S(K9^e^_kUjP7mP4)LDCJ6-)UU~d6FT>@6uiGA!l8UV z80s_ye$+9&8AItbo_yPcS;;Jh!$=>@F5~nEOtsWtm`m7`Ug}TZh10X0$VxZSk_c){ zlPPFVrPeMc1g=aBwx!UiMS-xMVU3QBw75MwN1k$=`xk}x79iX?JVvL9bUICRw353I zvr)>FBpZa52FGeE0Y^2RZnhG{())B!BcH%t#bz5%8lpS;TFndxQe#kev2Xh zKMU|lZJ8R|@GNr|gDHSz1_Qsby%%q=%(|g-o8vy6?(DZs>(|-)oi!Fg&d*C-i5KHJ zj2v$Sj~VvZJTk41Fn?|~;482R9*hYvTGj`MFZ7zN)S1$VnXtW-odnwxtji}}eA%9U z?$3-#(pmy7lw5MV?P=(?bvJy*4m?Z9TMGsS?_|FOJb)>i8(_T>v(anFFJ(ZS@aKm+ z&P43aNc*$Teh5F$h7R2pSP|8g&EnXlgDSH7#AT36qM7J&RgSog-}`Cm+rpC_EC&^ zl6pJcKlIJQZr2TA@v6aV2;c8h!8F#LP?36*hoo%?3N$q_4h9Rqv!>OyXO`y_(vgX* zf@r@Kmz0zyNEMyDCzMAp=SjtLitq;6FYf*(<8i5f6sv>^p%g4kS($DaSXuI9W}r~R zEd=2hMh~_`tM7ze1%?c7WE|HA&x__ppI{6Dysa4k6+&f+D{CH)Yz0bE?R!qs5L3e1 zJI*~p8IXzRy_#blpxHzU9Ti4hAs%Ga;$nM`4KPXwHb7{11h3IYZQd;ND#Jkcbsm)8 zG`Xi-avcp#r(yFa=?_WtJYl+Vys$}f9Ntj?1X$d@p%diyhHYDUiL$lx|L2TV01$8oM~_De~<3p z3APR^dWKx(5OX*~=*$ajJu5cKm3m}T^czRZjsYxg4>gf%inHyV`W8F|)*892rAt9? zl7~zyUSfrWk`B=JV4VDxhkN$p7hkmQ_uhhx`eu8bJLIFLFB}W_RuoXmM34OzZ!Z6q zOCYxKS|>=~vc*ftodW6@>$f=atK!2v_{5WT^X}{Izu$fhL~0hov)}Ih)er5qtFM6` z?qRC{y_tH>Dg-d=jCDH2CiQ6@QYIqLN^7#5{O4hs%W6M8in6=^{`){LS3}Z%3}yat zTS}hh!G|A4P6ZS7fP(JmF}EdT&{k38e0R;aSd$doSCkX(I)`Nc;a!w zUCT-{Z0OKyX7%sct~KAb8$bzu^2a~7+TP>#k&9Nd*6+0)cidwqyGGa&w9olRNIM13?Nq4#rwD zVf|vhzqYN72pj$OI)}gtlmhx1wtk{GA(0VuzJT1kl#&q?dXP;zBrI02y;6(83z5Aw zQ6?lgT2P35@YqvFTP^c)3>grwDoQWhw8j05uUY}^V2!2U`Xxjw$ZEpY;sgz4j$+~B zJ@qJIawrH@N+tQJ|Co}0I`q6ikRSRX0k5G5jj2KX-^Z-9KigA?J_A*kef}VZZ#uZa%^Dc$p!XI4WqCau!usI30~~9tg?sH-b$l(+~v6EQPo6K;eT) zaKB&sj=qtPt6Ue)POdJsdFV9~?0lz`B;JXvBv;hL-}FYd>~!)mP)fNAIXXB5G6qkZw-IqwNnR)d9 zAjys5UJ!OUF$Jm&)aWd=Rvrd&Z2cqKTShld8fua83+w5d(BY@xx>N9 zIqK0`Efr9L+SeqcW?Fn!833Vfta7Ygb-6~M#e|)lzSwh{Lifb zm@!CixugUD9!WMZ3QZW{)6(orJiAtyGomcsn`q&jt7zr9cBHk-5=KGDk`IofZgbV@ zD(cZP?5>hZd!}`YDJ2rY`uym}K7~gzVf#)r*hv;%7`NvBAN~aU%Vz~cbrwj@AY43b z*HeZQ0rcH7+->_F*$=1ZmDXL?;?~cfU;L|Gd-KQa8+U(Oo5r4o{r<@tcG{5>7fgk&jEPQdRJE(fzF zZ`@5}5#{JfJe_(gq`3*WzpnzdhsX4j_^mL}BPPd!C?k$U`10@>hvx3tf zSSIto@4yk;cHs_t_Jt=j|636}UqG!;s_5vOdemEvKn$V3u}T+CEN%0=>d8io{r~WJ{#wlNUu{rlnGh zj`ErUTr-Svt3|<#4h{jH%H;ZBQ^DgYz>7PN6o9v*0mYXf>FOShw+NX7Mt6PZpoJz=8qvvT z@seZGXb(l3pH4!j$=RhgI7kVR_5$TIVSLXVMDtCZBUYS|0`p4;2B_K_OaRFY}BvQ`i+Q{H8nPCl= zoO_9l6CW2{5<1CQupaJGH1PbrDte~%iJjc%Hn&g8NdwYl@-v%cd_NYb2Wx1S8|Y(^ z$ca+}QZI4#ZmjY-7Ok#5Se7(b;*0>4X*f4Kh@xM^a|u!{9!gdeJ&|}1>M_^QfHlSj zbDk&GtawA+lrxtx?8s<{b*GtNA@HOWeRzSPe0dlia|##PP>Vo9Axv?u2n4|xa~(@^ zf0ppBxH;WLa4vx%igF9BtD%M_nB=nXI3>Kt$a9FXf0}EV(EZ~Pg3uuPNdwy)^TW_C zQrh(VVmKQ|@E%Zh2xK2~F1tbBt8lB7d;$58gZuZICyACXNGjF#h|h3>8npm`9VvoY zt}cX)w}=vw{rlb_H%Z|=h5B=N($feKnG0ih!d_6B3H;2;D`YcwI_kFJF?y6?rOxu0 z;>%~LX$lZV4UhC$X;!)`eW)8CmqiEc2|`>R-sd4y<-w|7y>gi~1LyC*;}<^0klp%4Q0xBly{K9G*hhcPcXDn14`^g7_XM74ZfTWm17SNc&;y{M(t1Yv zAu*t4D>cuSV_^?q3}m2q8%8L8=ANZfiUJk}p$9^b^Luc2DhS~ZGVjquI7&+LEQ$5? z@4x*6-8|kU3jV0EeXfC5ieyWxy6PW)+b6Vntc%CqcQIEAdE4EHh5?cA>id! z5`f*P|D^T3{xs4L*?@t>FK*vy3oa&9E1I$6H75Z|m7$yn7g9bD!TJazzaF_b%bq(0 zM`>h&HT8~T(0Hu_PrN*G##Sas4#1AWz8zUA4tV$<^hCklVuGEh9%4AV(XI0_h{qI765^DKQZveby!@O&X%hL^Sn^ zwH>{r7;^1+dpF`J*xK+ymu)=Hx|+LerVTRdJi>!0s`J*bg~^0+2xNkc(_!X3#-pz6 zfZzbH41p}3!x&a~Gs1d+hv#G_*<4qb>ncBqF*!z#P;HJzG16Oy zSuAY(AlCLUPJs}pe}B7iK{OMlRXDi?rLMMWer;gx=Ol7sW*XUp_Z7*#3@Kb<-Rw!p zY|`u?1YzZlTNz2Lzd{kh#N4aKA$1LZSY{5J0wgFz^LD6jfWq6xIl1 z46xRfMv|;&cnd=RjE>ejkmdz>t zy&$eAlu4T>5$y^Ubr}flQ1UEO!1JAIXR?IIRD(kW@8k^yP>6oO1-L-&hRAaiSLGZx zHi%fdQwn^qyhnHNnj0VB3=J)Un=P_fH;?j^_IkFA4Kt1ob>2sDXFiazl~cMSQ#8 zH5S#{bwXJdO%e7iH(P)gd|kXNtRIAz*h`xC@mZOhEDnO1oSzj7ggFD|l)2zhJRzEf zqJ-S_5QA5@i4G8Yw(kWSc>Zxd%h;L!NfPt6e3Rv^ScX#OeVh&Z&AsNqxOo3Wr?tHL zrrBQN?<$bj>P0!&_RB5zoJ(Q9&oCc<`@DEKc*%9-0E(m7%pDXYzxGFrGtLi+GV;7@ zERtN_hztXAVsl)BjGM;xc08?VYkq^y2)YuAgbO#EXa3kM!XzN(FfgXslm&o1j#r$q4sIiJPe;NWX>0{8 ziQy1c;MP(Ef`0&^wrR~Od#=9Kx}bX*nWrIX17zvb^^Ogt6`s2OA-|0>ui+hSmdEuj zf<(C=$bW6;F!QSXlh>-S{H0Le>z|?gW76`nl4&sGBeX`Sb9kJBXOuhZGkg6d+;3Ps zHfAI2lkCDPujQU}BN&q{rRZG1IVE;5dWnSqNnf(+YOA^Tc6+KCvi9BIvWd0L_V@Sq zSkVsF`*}NT+ah9oQ#CD?+G0Q=?NEmjamSsDxDbjyn$HX{y)bG51^* z;aGWtyRW~+o__Wz+r8@+7e2lDmXFb<>rvZHTOjo*yb^EpNtzWeqxO~B20qKap<97F z_!^dq-E`Y0Fq8z8Scc(D=orJ#!{77leON%PjHtw?S7zAWx^8RXzKqd}vT174<@ z^f8c`C%cANx5zI<#5~B4|2*c015|@k|Fkh z`UR@Ft1R`9P|7Hfu|AA{f%}L%IvK1m!YIZBouWA(_ZlQ=D6&_5CDrRs_k&4vA#H`v zT<<`hb98CQGUa#YrU@e>^ZC=2m66S046!u-B}FBpT|$wE{?&Up9pA;{pNin) zfjRO{;>=Ua5Lr7xJU@zc<3gQmB7H{ZlFPk(=}NnZ`k?#2^$lBc_fKiT!Wg8570SSZ z38S879yebs38_7At7@u-=*X_K<+7VtI2liXyMLB#0#Im^g5+KTv%wa_-3h8*I zbZ*Us4lJM@H}AIA=2I3~76;ipmMC)?pf_C*p@n&_QDqiw&p%~gt+^V_1wsi=<^rqT{&Nd2Hca z+Z@ULxBm0jX2;*)!zf4=eL~fG&|&G;1ej)q4KsP>et1ZLp9DxT^59RATZEaF+oM1@ zd+kaau~Zih!9~WdAO{AsefOUKfj$f+Dk?67XZ}r;V&F+n!&EI#a}FzU6clH5<1st= z>z{DGg?qa8uKQ_&lVZI<&lRs4rL>@J9OH@7i0XHK&)mUrx$`DMjM=oJqGzCnLAWZF z5NP$WS8WhB5Ubc|Wjn5eXAy`zR;awxNf4oL{?Bua1yiSdk;N7+vSAg*<0(farvU)y zvbN?r_!?s@4#H_ZiHAv{KVG31e#)lfM+y5TS}ggy8NL^i5?e%}ws=@4_#QZQC@N32 zLD02}ib`PYAEB&(P%G!3Ap9$K{le%VJe1RTg5)WgD|w8G+`CBTqNBdvj*qLI43>Ls zqpe+BM0B9m2B-&|0vy3kvv%C_Q1ZY1V_?}3&Q(l>LQfa z#mk=7_an?_h4TBz6;=%le(l!t$UhEI(on;?Vy`i_%Bm%HC$My_?ZqIPRb;$W=uo^m zZN!zUR@uW3K0+9j4%w7K2sE~G`6|2T?t2M)682_!mzS5*da1_N{P2g4v7?3X-|p+K zrMB>K))z2+^73pu=b>m(@4V(Zm}V;6nh|na(Gk~K979^6ZxKQVfsR&>z4PKwIc zN?eYh#AZ?;fPk?^GGerkM!JMUXEB(%C!qoC?ZtqIvzOkjq2vJ|3MqkO06#n^Htow! z6zUYA)DS%FK3Um9YRhvbnj(W3+fTyIZL?s;B!kzB;*!x$ik@|hoI+;K%aBIK&7!>2 zwL+aIrcm56fMvML15-m=wNyep@)^!A;fhQaB2$NBO_8C%-1+zp0S6_|rLhEF^69e} zy!u=i2CyFoN8X|E8$ohlToj0NIh=><#U{}D&d3REO zZj>4t?kxW@_5~M}7i2jHxL`~Pgflls3ls(CnC($&qR9!9YG-waa$W`MT@4=R3h)`C zoGg0Iitv%&r^%DWp*)y4-vXLQ{tjic`h}X5lG4;kVQ^j#=Uk}k<3`Ag;4I4f=sYSz z2;e~osi*VnJQ9+`OL@aWVq4=*rsTXnZq^inCz#D3w^p@&v&8;AC}vka zf%nN!ouZs!0jylH5*Tr%?SJM^d=Dr|CUFMEt+{fY*7@2wLVN+Jwvh7fobK*(j-5AN zO@Xu0_t$9a1=q>1W^j zhP{60?c}`%2`?=e2qBtR!nEO%vNBGz$+&-C`{w8Do#!6`eW&qpAUHX*>rf5S0ma+P zImzeHJ8oNfo;AUJI)^tUS|@dT_A{Q7FQXWzyLo^V-2u>~em`KJes|qrd~X;xwgvFS zz>9>$PVKc-E6BZcpR(9lfY^9F0`ZJt$v^$QAKKuv51KWnXJw(KJZM+v#oJ;ur9!G9D4u@60WaS7J)3&yN9H;BXIq^f?i%HiHZ<=bt!AEk z#yTJ!2tM+XokI;*1YTnZ7WL`o7JL1X|F#o%e!`Y`n=E3q+oG74_SRY(X+2>z_k7mM zra=fY*CO;D<{lk6Nt59}JYW%nG}mRVg_9l#M}fZZ^q(yoff>a7ddY83ldpM>YldjV z25R3oZ)=SeK_vX<^UuM=5d!dsdNkJTYkztS52nrNF>kqnK`Y>Acr))m_PTxi#>=UJ z1ijkuo&^AyBmyKNLkiv9v@I)^7k-Rg5J15#vm+l=V`KsFVNKUy*vNR@dBZNpjH7ic zmZOs(S9e~&+x|#N#$s}9C!px71m&l0;jtKMCyyR=3h@w%X!p&x*n_`&&{iy2YIVns zQ=rfCz#ZVWV=Q8mlvdg;H~xzQF)4iJB?m36lN^klJkqhKCDesAH2u+;t{n3E!>Bk6 zJ3bv|?*JC*AT-%TXu1XOzMp&8GUl`4pjZmm$q&aA+Gu#XO;8Rq&Hb0b=tGWSV{&~& zv1E`)!Ez1i>Y$PtZT)|^MA~PBH^Y%-Aut>T&9R{|!UQ5=WAjiqkA<==8Th<_Od}5n zpeGo`sjly?Mj2ypP7Z=(HCw?Y<4}Z>r+VEraTf4GGLUqN6q~#~m4-=v`p9qVy(|-k zi(=(k1P+?z;X%Qk^#UPW<2}e7Z5q9qkLVD<15$ZvFoE z?sPnH?Wf3RXz@^FuHEP-ALK!qh$d~p&t#N3FAGSxXIZH_?!EV3yZf#?ou{WoqH}2D z>g018gXWLLIV;bQ1?0xhW$fC$%U##2)I=eTnICdwvcxbNG)@)ytH@KmsATnu@Kt8W zwRAf;a_p$}0VZH_5i;Z-NZzZSPGFWGyr?O8U79b2M-k*-zW-Yc6Zoli>oF7w=>(E%Vj-?!BZK`X8dyNp~d6(|6n#LCM z0lJvi9CJS9ZavJQxGCL9StA9M09>)_7JCSiV|k-7gzo$ZH!i`|D)MH|Jr5Jdbxc{1 z9eMHz9AbT*PSKMnM`wjHm#mBArB#k;zl*jd!9u(e7LLFo_5-+42vZi>_NyNKvo z;>xU@Qj`?hxLkYLCHC@jPqR!|v)q>`fuvBzYj^Fk&emp(3dTgulc?Zgqrz>&4L4Xv zW1}+`WL)(3Q)9LN9lPQ)pQYpjv><|L0*~;}!NXQwy2#!;aDdJM+&ku99SbtD^IhJo zsiB@uBiA@an;lnNrSdM4ZQN*CM9_y64f=SRP=#cR&7x9~XByYVuJ%m4U4uW+lw?ebl>+JjI1+2vBF zp5&I|*1c~cl&A?&+Y_Hqb@TwWe@fGF53YEn~)(x|{bm9Xd#Uf>MtzK_xaAIfPQ zxgwHgh4VvL+d;}zNe;>&WR0n`g&pGLfa;B<%p?b*^crJD8?il+c^DloSFcULIfJ-a z5_`eO2?0LXaGVr}|ol zr+@)TpK&^Zx9bST%S0ORwEq2n4$aYrdT7!l)7_}}BM6U39uTwQ{?$Ej4^1vN)mhE% z>X3%KCQHMWCm^U5($b{PI&FXE^PF66ZV<0Iy(NuLu`tj-?&U0x1>Q{QB`H6ux0yTv zClE;bTeHaGm7h&O(Jf{TSDlO93gbo#w4qpaI4-{rK_+PRLe5dS9zHLH#rFh(gxr1o z<*un=4G1-Zj-U*pVl!j`E{D1?pifNy;^%DF1*YB|J|M(a5 zY`F}JnBrgr$1DOtK%?kQ=UeK!3M!c|Ve zs{3{jf+KtPM=f{jHhZ6(RSx$Ae4gvfJxX|bIneHBU)h7eBg6v37tVvAh81kb$=FOVjxvH@62=U;lQ9eih>U9xM7J^kjp76-#kI*dB&uDZ@O zdu?g!w0wX{?PCFJ>K}tZxZ7f@wpbhhu8@Ryd!cE>V%A=2(V(hJ0i85M5)gUoS8S@K z&L&bzEOf(V76R&ZBogX4MHnbz9wIt363Lzb(U=9hN85LQY^!(OWN)_&U`!DjT)WL$ z@B2^N{K*ULk*6NB>p%V_yYI>8?1qnh)$V)h3ERDUw>|mzBX-Vh=fN5JuBEL^WzA}j zu{X$bYt2_)f4#-5+(PqSh!YT+{e*Q6SfYb?gV5UYLMc@_Q)~wA z(_9lk8HA7v0}{Sh#06p;ysT&dKKw)phsY2_{CEMWcvx3BZmeq%4S4c0=v-M7;|P}L z$4@DvVD^%lAqS)AWhgqC#M}i?nn7Xw%{~jr&_h$oICqgD<}!dBRQgDzRZ@16FGA#c zm>(w(C1VtS<~U0LEk&vjHE(otDhffRPvn8}56|(uB0(rq5AO>Aiqj#3P$5w5dpRzW z`+B<*qq-8#Ck>!PnLC_(6MEu9KV-+s)8gPCjd|hUg@I}=^gNft1p8evbr{fjjbB1} zo(YJOS0JC9|ECcK(J_G}U@*Hsp!ZJd4d7ZGA;CJ6E3&c${ z3z$Ws^Kj=DCe$epKqU-F07yW$ze>s_!HH#u(%&jpJy<3{g(=RA0QLe-hy^r}L};sv zTpO!}b{W^Q*nIX3AtdMFXkoD+V_~pJ0<}f<6$>#Ok<3DaDI$^Uh!&I@h_^P%kA8T+ zJ@n`kE}s>l+?y6N{q2%T$_GymSRCPzDS#Nx^5ZJvQ6^m|?h@*wZiMgft~*e6Yz9}n z&q8!wAqzW#g)fWH%?;lZDuV%SvupR&E+6^qb1wqrOJgpGaWSb%fkNMClO&PlB}Ega z6z5?D!nf+Wi=3dZ?j-4c+gB(?WkWJ2BJ~dfwW@_2f`=5t#wgl;o|Rs60VAEKP0Iwi zw%f^v0#somPr*zPO1Lz@24TBcCS?P;pZ|iDK$ms!$T6$<_?KM>XOa!$0^ckYk>$?9 z_qlw{I$M6pxz^lr+D1}iE&bwkY>+U(GAP9M4mJ?;4Dxct%GI{D+rR93bND__X#r|S<^ra#WX|Gyq$viY&-P$ z!*>2<=iAECV*B98Ny{uPH(xUKR!5IOYqy3xW|Y0%*aemd_jnNS=FXLdF`uiY4P{7#Yd1b~RubuLM}1}tzk3m=lc_~E1t2H_sQg%V zr46NX-D$Mn8G!xf6L(k|^;ZWD9ktv~eA8ZQov^rFpTRhavSrtO)~X5pExqQGR)b=x zy!sP%k~Lg){b%f%BP~|7<0k6>+;a(QMznC#@#!FNsmnv!ya6%x2#C|*IJ$5U&YMNC zDWE{fI>s_9AzfM)=57+AH4~~p|(?MMC>G?c!W8L z^rU2MFR6gdq@xX>2_a7sqtF0F&L*pX&y;-A2LPYz!?;v04|bG z@(5iNhgp^6RoGK9TA2}jP9*m3GsxU9Wa~63lrR*(TDvKjIz3Hxm|GD<#3&gwXNSx6 zA;Y-Cy2lEaO0IBQ`P-=m-n`%i^XG?maF73SXmAUDnTDtZsDs~m0hQxCCH3A)2t%kd zc*WbL5W}!~W>65aSmK$ia4%p5sU%%9pPyqQH3@=U`%rY4aJ)QW@zjD%6C#NqA0z)< z#zZi1>@%MNl09TCgzuE2lEM-&BmlZ9KsZ2S4X8GcD*qJ19MM=ear*4Ypu3>~&KFE= zP7DgE43bxWXq7FemgtVJ-NEa8k32gmLgM?GAT5IlStb#3@len?4{L$=Ktl)_Mh6kv zD9eSGX%~gMHI61o;}euu8!`=^y|L<7$sP>6|A?+>|CpU{w1E1wT98)CKE+Qy~}66_Z`ckp7E}4-pyi6Fgl`wu*$TQ z@|ETr9kr3__n3G-mtSIm^aQvb$89xWhXJ6^ErY{07?p$g2)Fd4c=XG(^);bHnt8}l z%}KX7h;uiuUq%1XLHnSg)zwyxunD!;^D^l{_Rc=Dt}bqTkj1WDZW}UVEe>Jw>M2O9 zqnJ-T#Q3yK#yoH16r}3f0vV~6&b*hVP!>R8Ftxolgr_)(5KE7uyaGTCZ?t5>NQqd) zi_nou_Y&U>~j*&5daWL_h7g=69ys1N7wvooI zd#S||@Fny7OD!QS6-uaMwgL{r59*t(W~iHXLlw+BVNB}ysyOdH!ht!^v&9ictMBQh zq3&X3%%NKg&>T3AOkO^t}p{7yMG9S?~+>(!a?>oP^>ZM z-G+A%VS9*DO&4#s1LUj%l^1hP@>&4EBGz1DZ3scQQ}DvI)Uo8rH@j{r%%{S30p<00 zEyUYv*PXweHcb#0a9?IHG(>YZ6P4r`QI7S1fTo^u3PG*Bb%3!412hTc{3$5O84S8v zj07K11lMzr9GjCJFcLY!g{9|PZ{AkhJLt7S)|0;^5~IR%WwJD1^IS*I>v$ScSVB`doG$0YGIU-kO7vgv{*pCP zPgi~TFwfKN8pL80T^hXPL+U}-rES=VWr?B$POLb2FhVPRwgg93_i(u}CB-(BRALE?B z8&o)S3Aw(%p-2OmjDnV{P(B{xC_fKYkFjnLkMK~gTuz}a@1J9Cv20Z?A(o7)WyN;% z^}kvy-PJd5-C}=w_Y{T<9yj4RAA)z)nx%H=)xX%{f_y86aJdmrag0(A40){YJm!wt zyzU;r4K$Y}AJl!Ki@AWYgSw;`CT^G-yO{Wdg*wOj783P@%wf6d>1?)&9OfEhuDAe@ zLN5j!HDL`$581iP7h7!uEnM<>p3jfq5%vJC$xg&uXz#MBiVB*4o`P{>z!J;y>E!W- zB`&J6EXbn!TAM9Sh0Q3XFglKx6j9ek2l1_o3#_55$BsiS)dSaP-YQzkz|XpH%8Fzx|4&~Q+n$_2TwKI>ned@!B_x18_cezSi(C^&UY_aNyM-I+%o#8JnV z5*5RqNwkSrJ`b!_pB@6_(LX*-$b5o4AKnQ0v2fU%@b}G6$a_iv3)Wja=S+E<_`|;vvEk2Z_Z8Z|lI;V`Gew?oRe6q0_xIT8mSL9%OpA%K(bf)1J-aM?aiLwjyvUyZ-LGx`vlz_C zoXr`r_SB!Avs(R4bmyjjxyBw=(KkI8XBv3}<6rZI8|;BMpOK(MF2U)8(p&$z8|;xc zp0&0&xOvDxrC&b%z3vsQa$j7tuqhDd{@^!Vj1Dehp+O~=z@qoFVXdAEu1A2k95)aG3%?T*Qlm-(YTo_s-)u!Wp{S+B zcKld9=UDI?7h1^cTX@Ku!5gFdDvuT(t!I8V^0S$To^P|kwg&s+CqHKU_wRFKk*AFD z;XdyE!NPP36i;p;p^den#5Ofl^mgGhlXe?*L{WS&B`L+KkINg;MK0tO7j7IURk)AM zV$(zX&I67{Vx%w;l-g=2mTC?iq>tA!J`dFrAD1QL=1Iz4#(>Nql!?vrfRj($qE}se zxlPkDc>Cg zxf#P_lk#7?dL`W)PNTr5ZDo0h4R)M%A(_F!KC8q_IC0`Q7&pqrN9Dv?x*h&%P z105Z72=LMZDA%F|4(Mrv%QTv>q{muVP7Qc4l{v*0M`^>ltT>bcEodM}=)wbEUzlqd z2-Gr!Vl3Xl!PZergiWR*HO%tT)UGNL9>#V&y)dhyZPHYKH@Vs%Yn>1S4n6LmzRF5T zwu7fTZFrK}O4eCYETj;$JPJeMhffUJj@9K>^l<@xhvB3MR-b%4_~mI)6s3&0 zZUu`H!)!I<9quNPAGQIP?5lrWu0 zl>O217_tyjW9Y7izjl(b_9Lu4kOSnhL;C9LY{^%DY>l3DYUYw5Psp=PY0P zf(%xE|LI@-8o3Nd@va*PIR@-EKm7@t4%NZ$o41~WI6iEH-R%gaIa2Vs5H+OQo>yK# z9^qK9--4Tx0G@&Tnrf4|BC+q5{(-g<=Z^dSRB zI~~yiAtJl$bGO>FcYO)yFtWL)gXei|sE41ed^ZaoBNVC1T|eu|Asaa)D$nYZ4_V=9 zaC&H%Zdm^qn8tW^kWwuiF7>moKNzsQS#cE!+?- z6pbU8>k305_!TPU8Y(Ln*$vd&egBSc*ePm^Di$pQdc6dtcY;s`U#}IZY2#WnIqo?r zPOQrt$iIo!=$R+}2%q5zTUu3V+jie-zMSR2nBm97qw^^=gVLH&$X9td#=JBe=sgrf z)vv!`)$hJ-mCKje=l}iJ_6|hOV}wn8%$?972t$FD-+aolQ20`OHZgow~E|gKRsKRknih3>~A%Wb6 zgose7+H3RFkM)v*DRv(70leS%lr+GWgf_j@5%E455EF!F%d*p0Us#b8dQU57L@{(v zX9wXJyn;!}69|)57Uj~_{y07DP?&fLg@r}djUo>w93GF7m*?5r-+|*zM}&bP$6PO? zXCA)FEE|XMf^Z?8?f~S#Lcf(17g&E^hb<|{Bt#1gC#^RpDoh@WOW`}!iLun46 zkpgm1@mAB?19^5lUQHO~1Cex2NUZ5HISXYflhMSbV(Xt!d@AI32f67eL`$V;81Icrr# zIed;75*RqKD4Rl*R}7H-qSQ#jo{>Zkpim<}m7ASv`B^EhD?u(zg6Fs%-B2%~#}SN& zo<5MM2@?w7>Fso|8Po zkYBN^+=}7S-ShXCWTq3DA+_Wpbr|@h6nHZ-Rq|9SO;J5382NocM7m#i_Cr>98kA)J z8Nt6Wsx!*q%pa2C9I~9;yAW8I13XZ2?ip@6FDR9X2ys7EL@ICY*zr1-|5&wp9fiSo zgYvBK9tE4_Q=CJOg-^M}nv@tJgtLdf3RPxZwBzaT>$Wd^;dXmt@0)yzR|tJL4a4Ub z&cnI*sA}}Y?7|lS`nZA54Y`n!Xu+y$j*~AbL+LF=3FEHo`z6)+pzu)>%9Q)PJf8{(u z-TtL3m)JQMUrHDSBpS2|Q&^6qgVER1B(n+1-~|;C?o$m-Z%3=O9olOFJd7O_S~r3a zjH2+h9|1ClkPC#f+3>v7ojE@}3Bd@zCBj}gni4#msmV!eY3hTnX%QjCE|TwD7aPjQ z9K_)*wRQF4%@Jf`Q&Z!o-Ybz@Q5HqM-jQAk#>ttm zsRbMmH^phrJwtw}dmILglmtr+qn>E6oBIf!Qvw(TJ_Tw{?Uu$-yfY}dMdi?_VF-mG zoY%ut5WS}zabLi+FJB;qA? z+9iuptu!gj(wN7l&Mq3W(uIO`w6-Y4q6S+m&~^$TIBdP34F{=-3J{vDq9nkJaPNks zcM8F!BKBc~R74~pL6pEjq5wil4)Wd!u3-@GIhx*S6BstpaCG)C*D4Ag#t2Z~GY@m2 z)-Iv*6RvhH6GUM!7JLAb;nk2>tL82(Eya4;TWoE9s%68inhr>#3$IVgtgJX6@0Zv6 zdod=|eFJlid)SFbQ9CeWgRr`&1R^&*4S<0_G)M6U!(2ZAas6lR;XQ?A7j}V zpK7a>0V;7B-OtmxyUW&Zfr-S20)Ztdkq{-hcjdRz=~NIY;22(GC^AItdW2|Vgw7!o~&( zZ(^t?VN68e^-bYXN29!iO$bIVs%4o<5yW1i0&cz@v7j6$IYB94A{P4TYVkPFEHXmC z5g#7A+F(tCu%2SykJ4IelGFffW;_>8&q!VmNwJxvA`1plD=J1`PPxUd*lID$FR=Kf zTP(bEwRx6rvNRZUa?ZWLE`Q4;oC5YAoQoi2LgW6g23E?p&Ohbwk6 zohLbjuaLS!#&a(uQ}wjILw_Mz?Oq-q+My}YVBA2 zOUO(2!G%j)i0u;?;Zs8C=tKyZh6c!K%WMggds0e9=i{Zb6S?49>b*K4D@EU-_ziMpm%+Pwsla^UmKHs~DOqxihbU;x`{zy1Dq&RkE3?cBAK&-(5A_k72yuDS&@ zU=|cc7!8_E2%~2ZQ51qW zIs%8n39Iq5Rc*;fS)vlzH-U*or@sZ9gor$ujCjIxlt5# z1|CuhV2%k`Mm7QbSeZ@!4BpC=Eb6l0kQ`_H(3O>hhjbyyYo79Y$tzxmUG&V!7Y1bz+@H$w`I+*o2}E}l&<1_<5-V1+bb zZuz;Hq&;9gAygL!upu>(jt>2uR$4$l4*tX?rA00rTg><(c)u6Wgz6+?2ssIG zt_2FL((*-kf&-SCoJ4`M-zHEZxuX7IeT;B_h@t_WXvG5qo>bj1@%`LK$OpVj7V<);wYNB<@c*{H5L9?I0K@0JqH0 z*tZdnq|XMhgSyEbs*Cn0-q-+EfxMLfp;w_B1&#>ETZ@mS?;uf!RVd+9ewG0yN>yIX z%Ulr>&BqgqAl)zvAR-ixL`mR5gzGG*zb#8CQHh?WO%K2m?q58J$~3}{3FPV{d0!+R zP$b@Pe^0xuC@H}B7`6<&#PmdRWUM=ZkVI^(I$+Ms{)3DiBgDgfS&^4aw{j2X^|BvE ztlLk6R?1rhr&G6a)$~QjCAj+#MTl3(##xLPKgv?dPMdX_IadEkh480&EewSykcbR; z0W`FZCDc{pHiO}z*Bn(M_sK=LgoWUJ!bEu3kMehBQ228g%}(6miOzu53?^(k!RAxy zVv1sVHO5tA=@G~{dQpO2(jlYs;^U#pNjvp*4DRF!`)NJ|N9`Gq>f z-r~pIc7HOMU<9}piI7{eR6ru|8W!L3b$0blpRnIP@DSg_bi1N)eJc;nr_bjtDY1>^ z`S!>AzQs-??1KC4Ixs8O#-fZWuCPzu{qI)YK4^7#EE7@&Rr=NU`T7q<2^6iH#vUCMCLuM^)J+1+$yaYj&g+`Ufw>)~*)(lqL17G?i<3#~n zaE)bLc&kMhFTyhP(!sdXMgrtJi1W)rCl1F4p-%t3+WW5}HgPpIQ_-Ni)qZ=%U~|q#(JC_v(A| zP$X5UFmlu%w3@g6YW2Iw z@=Xd6Pe68E3kV_w1&YXWbKTMl$Kp()#q+uC>EvFyNB>>jivXo7d;&%1plpvIwCg*% z0e3`M5joKTl!lPQD((+qujG->8yFt49$@3Kge8~f!ljDEK0xTphjD}5U?)yd`T$@_ zz@;|sUsh&19@3PxqriLT2vrmA!@P9{j&i6A;3~qZlpBNulP6?ef(iBIiWibR&Uu^H zS`GQ6lB^7Jqrm<7eid>Pl%V?qc{mWUxtzkP2~vUmJ|VUN)o*gDd|Xzr`H^z?l``8 z4BA9>Dsd*gB)kj>l;arSt1#|)B9vr<(6*^gFbyL`2xx)6J1c@NTC=+#hG3wF%e#+FLEGpxjbu%M!hGEgh)0 zTFUBk;e*^jW9@9~Io(X7!z0`Ym=RH~u1J!f@&;2@Y@+yfkwuiPw$!pJM=Rt@E~F?p z-{un#wyEhhg%vq;J=_tR3atctot&XoC@%HkVXrp>XPTv*}R>^uiC|2;$g0Z13{d0>5bM#4N@kSX*@9hVPgBTbSJfnnS)dWX~bZM{q;BZ zlQ8b*`>>+(%Pq8YCB5#ZL3l+FTG1v%SuugZguB9(|MbL3%l7ZNVYA&-&?emo6>RFCv8+k$Ao}} z2u-G<6teKhChCvd-ar1q_C57``}?b}S$x$tEZ0;}qIi3FjOhR>RBrI%L%+1Y|Mr(w zzkjb)edHswK_S=4Jq$vygkiahT>7OaAGE24YP;p*w^3xTyr^i&@VLfk(K69*+gFkI zJKbdKSFf@<$_#P<)^tM8Ri*qO9^kq~g|z=kwWt2@JG<$I8|*K?_;cFh$KFyraXVvI%LT@9fiN|K-o11%fM_@h&RsB>Rg)wU=D z4$}d8{2>sVdxx!k81MwjC}AEUiAVIpfm+A6I5Un11nMsqg>{OYU>hOB2`{Zz=*1X~ zXH(rdCZo#$^uEcHeNb%F=a=UMtxG*E9!5QGl# z638Qjvg61Xg#fC^0K5`JiAf0ffKeg`+WA`35dyy;@B`$0g$N}WfKfongYwa=^Pa&G zNOvZ#eMa0bc;O3t5s z@aux?*0uiQkg=gB7Th1Lg?s<;+W+z|8pheNIsKvu1a;5l zS?ZncWLc$joCZD)j5?X0jX?YT(Ly|uV3CTN@fRtJkLVgaob11b%W8{irmMk}4(NYSgL5xj|Q9PVv>EwKZP;ilWWLwKp z?TUg>+mJAAYcs=XO@o4GgN`C7rtlD_@X`Xn+!yCl*gXjMVr-CY%8IdyNJ5_Us-vXL zhNd#dy8sGGb5&bG?8djvu5h@oqwNAYR$f!N9GBOr_e|LZ=38GYR#y zIC3BZT`rFk4(Oxjo!9NU4NK`qH*4>|@v436%eUJDKl>4I^Jcq%y3GAQxYO?X)GqV2 z!%K;x3P;%XHaE~L=&891r4Ozx;Lk+?T&*CypMsT!1+W&(9#dqS7E3 zZtSp(%q)vRl6je{QReU6mQHI1iXWSjNdwP5r<|JSqwFx<69&U_2+dM6Nse$BSb8;{ zM*j?57VWnzT3W3HLFpf8#}lV9YU3$eif7Q?c+yG> z3$2qnlw@krVv!|2!tG%w5+u6IPsO5;;{n^K4bTkvs(88rC@M3nkRtnLWP-wI_DD3! zD3X0A*&d2Ok*pW)PjY0I&qdG&QqdspK9KlCP?2HoyL~9KaR6Z|ZHbsiII}lq<%Pn4 zGDF-|1Pr5`GemnfWDcWj&Whp)bD|gp_zI|Y7V)fhJd$AnzF6!pYANQ&TbyG6GmKYc z%*g<~g76Ac2m||&FJ6Eh%9RVmHAcBb5T3lkghLo+YEG@Nay)gQGbr78lw=|vzw(SB z4x|S!EZ6Ihf%5*CyHLiezJWpHchxl71rH?*xgJf3{0I-{a&m?D`z1vApHVLeT*fLk zAiYOUi!0SYF^da%9?x=;*JmkRnn4*(0xSxrwlk2DM*%s+9gq@J}DoWjfF8%&D|!Sq~r_kAvK-r28@rC~IpFZcddg zoK7d_lrm}*Ueh0rHb)=Up9m9+&$i_C=UE>-eAvi9ZYcr~b#>=7+FM{AIAta27YG>b1B;W>PmTp@5> z539?CRt1MAmL5xzc$QAylZu-IEQrRtNlr?z5j+!u39e{86)RNW0&n{X%Ok0tno2X- zlBE{0bh~TN8sJ(+0IH;suS$rGvL3vEBx2uJu3T(oFhV4Uy|*{pu{|%_Yyb5h zc3{unthuYt5?61vVe+W*$W*Q}(M!=Zo?;65loM~T8BmTH zyUBrG>`{mc#OjjEJWFw?J&U>ojAKzu091+3%(LnfCoBoJj)d%Nz!{U)NiMFqpvZm`&&2+-0=SZ)%9#|`B*6cFcDPOKPGgP?I*Nu|gBANJk@O0Mck z|J~iyIY)I4YN@lbgc3Pp8!(`V1O}Y#8OOf^ISDYH85r9*jSZNfEOO2W5J)IX-K|y! zwL0gVbHCqrO2W*0>;GnEy|v!F^_UB#>Z-bR>)w0L+40-o23g5^>}j^NDCTZs9RR6h ztFJi;dNauyxF^%6&ji@eM0l1$dC=PvJ=NFfW6E3qx=x&VyRHk9#T_%v(r(4K3G?~>~hXzTC^KoxX2 zkmnsA4)L@U5FtR<0tb($wwtzCfC_5>R3%ck8UQdxlyB3>J4O+48O7+3GMdET)h6Rh zv|geF6B1blx~oZKyj-UO6j=bS+9=V47(hcKtb=hDo5GVGEPbVHoWakr#J8#3`2_n2 zOEB&{Lxmg3bf7ec*;g7}He| zWaC~+(YdgvK9f@98Wg8f`bAV@6XgB`oSPzQHHo4g!863KW;`e*;_m?&zroS;YJ_P9&RqaV881sRHQ?iH;1L7f*5{rss@@V@jaJUKSrGyiY&@Z5<>&#~-kd%N4#!%2bczSWf`xCG_r|@86P&UM*EH5<}Zvw;{ zR&YfJNVstz`xE5Cn254qJ5bb-gjeDzimn8@Tv}CUkNo6j+wr%**lXLKu_|&faWiIN z1Q2Q^_c@HksSd~^gpTAnwAMA+$M3vuU1djXfa^bh%}q>n?hWD6VI*DMb?8PQp8NB(%9-TLiSR{7y8 z)>3wmBK2r1rF7x=?oVjOJln>aPFT^lC-~lX?d=^;+V`$oZJQo@44%}r_Wp-E2^WD} zq)S6TXwOXYQnT`B+uovM_V%tl_76Y(slE8dTa4v0tXq#=bm7_dryVa^^u^cFD{aJb zAy$r0PNxKAx}7Ba`4D+Ozgdf{C!@f6BcfqgArwsrw~L~F)j`*Toa+UOo&dliBRQV( z3z~)wj!@4CVw2;~12i;DNklNscK5%w-DYJ**_`Y|dLC92O6#->3o?ojBgCXslpgy;4UTHe#xgOY`Hh64UQ zNf$5|7I zb-Z+hGwX4J@a8m>f0(=#6bRf%c6`v^-mDt5nqdGV%#kr_y0R&I@DZs6=PcvSkNw98 zAu7!1ODMgU^{wc_X5#s$Qa;DwyY~)chc^ZPoK8z1@DFZ z{ZhP&O^5OBug?{Z@V;`68(-SKc`E}S;J_^M=DZ<8ZjW|zgR04n;AN6%(*Q663=mO8 z63D7y8v#Vp3Ws1L3=~TM9VllIh83y8*_qQb?d!j~&u-apzukS$J+^AaO1pgJN;`k` z8e4M4VrPBnHvud=>Y)?$O&FJ>)Sab(4pZu`&%Sp3I@cepVAd>KNIhI$ZVrzEn>&9Y zi&05rCKHRIk9c|&jT{y0&q#;_4M&qv`nV}}f3*0B9WFZR+OCw~-KtHG7(g^ZwFvtV zTF2;9=EuFrO3$DTOPRg=`WyC*E3dNkU%A}Ab?K${!j_GITXa>5DF6jqtuxy{@Aht$|2z8e2v8xG2Czo*d(Q)BJ6yKkW&c0a(M4R!=Cauy`LMgQ^(8#(@w4FEK`Z24S!{e`V~MIKu+ zJD>1mlT9CQx0JqGa+lSX<6N)U4yx^g~{Kk^7e&<2o*3(pN^<^ctfCA~?|KuBXVHPCa6$k9#fqj;W z0;@l^7wA1>L`d{Rb)Cg!%&?pVOWjoW!_rR9n`@=CFq(>vx9T1g0b!?o4K3Rsp+L>Q0@zau3UVwdGn07&kpZ9zKMb=y092|#xprby(YTu1*Gn#N0030A z4T0qzJNDefYygZ3oljMyEEefVC8R6}* z##%;7ifh)jk3r$c(-JqO(2g<$TIemfr+v)ctEF!soRC$ZKRq04dU_IJK2U=ka}vRi zYH+!J9m@~JIe?NFz3VR{1GwyjL^v;kj@Jr7ik3D%;V@li0x^j_#Ij@ z5v;4ea$-o)57H$Va$WQptiymj(gMoSm*XQ_l4x)|)3?tq$qcvi68tTDs@swYjRs;o z`;*J}WzA0kYSG085jMs}2W^TBlnfxJuF@x!XEn1fm5vD~Wf4huH-O)h(H@A>^x#oW z0{RhXZ&=5|!}62iEyck($^h5CeSM5M9$5f#L2}ZMvEdDS9Q(SRsDA z;nPC*w7k`Rn#1~@Qa#dOlORncjwSz;(nQc;Qt&`xVgb4qT1Zje`|dpct|dOV>;H>?>LjsLeXuYB`I}4n?ELhR zG_!i;iI>tratJ~31s>F&KrY2}=UK>2KG#G0@|UJRWCMhH*qdh`tV*1B-siXEva{)s z&u`hrBJfZzx7xkuj=_!e!&*>SavWizqj{)$pI~CS&zW?Sn!E^pU-D_=K{N~npIuv7 zWoON$F)F-u;pA;fi}u@dJGR-gn>N~O&pj`d>lT~?bZFsn0zM41!VaS0>cwlTY^6gs zdAJ$zF;-V{)OKuq9PfxI3l}A8J%~x6?hw8xD=8>V7_SB6ZykKU1Ry{l=bwzwdznS~ zYF(TC>W(|?-n(zLpW_w%?)KaHKHp*C`k)j!GL|}b5VU1+eLKiYKTF4(3Q*WW+?v!+ z5htin<`Yj@?O*S=kWaSQnSIA>;P=0@&|OH-%;9`d z?0Cxq2X@*8Gf>EUo;+M*Y2yv{&`)o&KR0F1Uw5PJEjvLzZGmmL>j5hTrk%CoyH*uN zLG9X~*i`QMmUZ4rduv~j)jO9miRePEB};&nv=b&o~(Xig3?uLlu$U14!_Ciu2J zx#y%EACI-YtyA_<^N79KGG%YKPg+YTfF3{upH|j5kX4s|ycN~=gT^HfO}=MNB6&m% ztY#EwFoL_Zy208}hQW|t56}&vdJv#cWFm$^pj8mg_7Fu#VP17fP-DIO7k^~y(qYPJ zJpwmv9V{>d4shiIjNd-sV>Q8|4?qa|V|bVqF9wjQxhXEEz@^^}3scbV6RQ2gNuJ^#0I*zkSSaR8pog9ztmXhFd;8 z@K$9|mzEO&mUC+t2lDZMOFj+9rHD${LOZ$s2)(D!C@axRjKX zqm=qMd0VAjT<=XqR*1^Dat{n1HFj1<4{m{zH}V<-390Bh^^g({;=2N`;c{_2848lX zDumM5I6sh&P*iyD+z13c2v59JorVzXBJFT;OkrCoPik6y_}q0ykcW%Bod8NewZCKx zJ(9~Z@^vyw5Al8B+V#+(yc_!?$E55|zvorDd@7~Q)7{=3|2zKGNeRuQK&4a_*ROw0 zpXuqp_4@RKi7qEqe%$AGQ-as+BuhnqyVtyhm95yZK9j4i+<>eZ4~s|txt!kY*;u88 zR$f-g=U70eeomjOrb8T>+&?S~lH6FevGdQeL6CpLZO`{+ZXXCB()Kyvl zbU6*LJ!>5emDKGt0+=awT@I>Xw->Ef^vrp909a2<9>wm_U|4@p2a#Wz5ff&ig#KRt z!^8H`dvDkWJKwi=-+ISBcz35AdT*CaB!gbU(jMY`{7{4nZA>Z-&UuasZAXg{U#z@gV!Og`Ox^_Eg?+aU1l=wOh4Kz^$}e3MBkg+FQc zJ@l{k`X~E|^+!1rCP7VVnOJ-zyw!RJsu1d%#sDphTXo4n``$l(-=5mK%|e)z1D)+Q zk33B)tQ9^qDV<3N00B9gkM6dnqP_O*>sM2Vyx;b{^Pbfg9k6LaT$1cB-Sn6hFt+l9weyCqNcxgD=K(2S56V&Ipx&mO?Cy+-?(XSGsAKnU`A##g(sB z6S6HofTuQXrp3^frUwqw9u{v}QZ$NT%<78xyn@aN^Ojn0G=$28rc=m8mKGhhbCxf+ z_YUoK$j7XtBujyFWjD2UUC7b z#wmO3iA{FS#b0s-%W)iI7>oH>4dK7J%dC;Y@T`nfs{v?I+6|JqojNyiuANv|GxBHA z9lgt%#md9{Vp^?l;kAqA*7iUNj)DS>^N!+ zLr@CAd{+RI4nmIG57yYpDG0j>hYO*YFxFvL%*mh(1+WbHDz*JmBxEkUpRTZ*^Hyk6 zWb7j-fDVeqYsgJ|Frs5X)Pxg0kBN)78pxql`x{P}EeT+c_%j1B@S-S87d=}rfBRA= z8t3X>2OWVzEwzNLcv#J#rca)zMJdI(oTD+1qfnrMAUu;|Bk9C~QX=9LPCjyU0HcO` zEbneY%7OpI z+`vfi$mNn!;hLvVI+71+aivI??$-qJQJ_8nePpZ$Ay~w)y+#RcS}zFbLzCb=PbGFeej3A zqn8?DJ@hwkdjFDpt9SII_Y{(J@9`^GBJOVnQy=TQx=CBNZ*hpGt5>Yx=BVlo`+ys* zTPId;@BP9vWWviOmsjb!smtPEG?cXOM)@?sgkQ_TI~!zOkoe-59Qv~R9rs(@ZagC@ zdl1&NI)TP01fWM0UQGo2nSuN*1zU2W$}(nT*@f%Ya}2(NVs&{&LZt@t`^gVprNxdc zDXcx!{b-V6fvSX{ot)0TYS5ER`W%F+EH`ah8$Wzt1D&S#KuE66TnqSG==70Ph^DEnFbNqX4`1oG( zKksrZAG_zi`{2_)VEqT*x3a%IU~{@l%hiW*@W6k zN^Rb}d5qTt2E{SFx_Oolva<{-x!hTc?b)rbxCWkQ-S}PW@Q)#M6ib*BUJx4fJrMZby% zJ}`;8xkVTozK*_0r6yXHV;CQOgr_>NibnwHAls6j3L$x-t|5Y2<^OAijKhYK! zPKP$`QM+hyuC*Nd*c$i00|jgev{1vAI(wlt$qwO~&;9z(?8DYc`=Hljd&k0Qr9+Ns zT8@1{XY8Y65q6M}T3AM*)r=6DB(Ei-ZWQBZAB4_5lpe&A%bAr5Cuw+`l~Fg^1=EPU z0)@tf;!_Aa0FX!>Ve;nS7<;=lz+O2)C@&};p+_hY-pd8lA}*UYX5Tn7%MyD56Ag7* z*}E@UXmhEpXC6%Kei=$H${z576sA-t%Y)S)3%ia$BMPZ09I0l*QwTH6AIWX2{4G(=>XnN5opSP+h1*UlsXKcjQts-_`!a=eom%k z4mLw&M$`y_SaP%o79(|IA4JI^C%8TpN>3`HA@RW)8=%}|M)0U*1MKQ=2P6|0hxZg_ zk$7Nd$N1XCQ6qMF+?ZW9BbrcXpjDwD#}VGTwg6;8G>SM9uXPlKHi(hXjM3E;mTo&c zJ>0)3Yl%p=4m?Xg3g+V{du_I-!>*qhXqSX^+C2Xb%L!4ft|DA)++$JZ3C)dAKz%D;^x z=R}MxxvQ2v!}0=AT2hYso`}>*BXce&EqUH}U~!ZWiTX>WOA3wpVo3NShvgwoaIYm@ z<)!mOtX|$z^bYZ=9IoWH#@4$@0An!meJLy{@?nf^C%8_@R`=7|neVaCcu1po^@?73 z-`7Wy?EmeX6qr{je5M%w&*!8aPCwiQ{r%-EP0^8QU__^Iaq6nw0+4KZs5Ioi|(znWR%?DUGFg&N9~^b z??t%4d{KPJ+TMTFYM*?>svrBcH9Y>$*7W3WEoGq5IzD~Vjz95x+q?NOD?f73wfj)0 zOnE$!|9N=|IuMkL^Jidf=UF-B2AMFkOi_w(%dZ}`GuM0rFXb%z!`2t=s++!NM@uU# zcflf?J%54SaoZi%PfqEK8~y=j#qzouZ2R)zBDz;UVY#eiy3LL*nW65;Uf*?{;1Y2 zhcRZ_x*9U2D$uKVhJ-9xglZin@QCtu@*tFJ3c%nCMtDxatfR2s?373VSO)bO9t?(J zJ3x`$O@jbTCas4Wu3pSdMR}s}4lc@0#=`?hLwME8&nSURsFH^aUX80f8HQCRFrE@& zLn#3Sw~Uu*089e#m^$$`M<^=@W=&25&6-C(ImfS$H41+vq2f~9-V+1l%&1F~k_kmY zodH4n{L~oMIM;%~q#lXovKbU(QQssZEGZ#le*NAV!7aMt12wavkE~bU+wB)86A8za0Kig&2k6 zRPlN&Kq41@RMZKrIzhirdM+U!PwN?dm(k(=Yd(x9rpovA5WAE=xj3=x_?|LeG5Ebx676ot&0S^QCP5|TM zgsLu zjggn^lCT;$$_HYA@lOB>8KI`izx||nSi}L{wdTv;>bx-4a>9x~ec#qyx59Q4V)G6F z78G-0Qf6XbhmD^sgU+5%7Xr>o@t(@|8x5`a`;bjysrT_&P01mfo1g1KJjXa67b9T6 z<|+U;sj4xT(QHC~sJtmu=^qcaA;3eVes_G;Dq6 zW$XIr1?zrmv-N)P42Y+#w*H(sG!Xrx)!;RB?tR}*6z#SP&Oh6ZA1$W->nJM&W$ipn z6fTx0gnkynZ+sOL=!b8;z~@6C9)DyH{mZ{vJiWFS&4(oW@DZ#~4-{f~jyze#u$NtY z37*+;_(?nLf{QP8R6#r6`_SsCkNe(_eookykS$hZHiEAVVY_W$BO-))dp|J_@ z_X#s7=b)CVbk8nOiYjEK)4+mrpiL6J8|$c(eqqV6Hqy~*8Ca9fPQPQw{(HugNM+tdT`vhypvc*e?SbOXw zq1&s^Uv4ix{U|xKQCpgoV3}C^pS<t)(!Eu5web(S!neGzII|bn5L*8NqMfNr(ZRB)xyj~`;f8jiG+P0 z3ad%-EeR>`V)DJp>Lv*5RsI4M7x_0)ceRjbQ+t{?LW?ufr&&2Y-oyYhEg>0CD;%O_ z>NTl5>?TK~MxF&J5!MY)YB$!tvgjjxSKSX5=cQS1T@_vziUW_V{m=&>jw7t4yu@Dk z{lj+odCO2pesIYiBF`Ic3n+c*0bMKp+1z=Htg4+nbQt{=LI1XZ(2Y+_f`z5lLFd&` zdl1h#nvidMD`g3^TxtYxRR~(szpKG=XxAR+5v?0&V8-mku%Er(?u#KqnGA4tU>^ul zJS@iOD|v*EhpAyinFJur#|fwTu)g1cgkUaZOK}v^OF$}D?s`|Ej0ebV)p5*|)ZWIC zHkbxCXshM{NXyz5j3DAvS)qfL3U6lwwR|Vr`|Yj9L2LE_c?@7B7G*+Q!-Y3PIJOV> zuA6pKJ;O{qNG*mL57d_niFXki?*rVC2vXZa9(;oF4`dDr$R7s+HiZO z5{PMnvMRR`&JWUBq8(ZNd#~7F@opQfF0#o1i)~#D-o40J#d}156Pab`Uzr(%1hezRZ zmP}kS{QN!^7vaA$!aG*9$Np)l3wV1B1}-}pmySTGIJCzW-}g)2AG3uhxCuf!Wt1qC z0p_@D#cI3ay6@Txn>N|U#gKR}00pG{5OZRLk$A3QUS*$!#1;vTx>6$s;^E>w@X)DWmV%a&7U}I zS6zC6b(}1={+e={U1nMgf;%}b%+3Hrv-#o41i7oT^80f)<~Edwu2 zbK$Wa&)H?ye-kdkG;2WkUH0DMu<^vNR(l$D-s)iva5 z@z6#I)rG>$kvlV+(i0%%(Rg5l^QI7_3NO_(wAi8Ias;CvqyiyUm^TwDF=)3A7ZXyV zJq%Q6QH0kzF_fYsRlnz|;GACZo@ z5Uc*^b-J~e+N}BK+XpW_Z&B^VcHLPy7O6QutSAUgk*Nd+5GfDfVIRa0$}xFh7KsxQ66(CEhGLjtVE#aX>iEII!S>WsPf&Y0%Z`w5&o0PgPEeYF zBKJqAOEzdf0)-e4lqay38(~?VfZeEvb58I_*+EjB12T4~tB#(4;dsF5HdzE13|Vm; zB`{-(K7F9`eEV7~jEGDQ2E~XFlFh?>-fd$1mR)RUa1En^602gJYaZD!U+;N z002M$Nkl4n>!wI3=%QFn$z@ zYyw&9LDo&77{{bYL5(Ws>4T#8g|SC+WrBO>(k+r1ryn{Wd80zJ6A?S~!gezho@)if zeV#~8V2y?`A2?4Gs>HLf1`2y>3`ABiMjuB-$|MRAUGB&{{in7sw!%Aoi@2#utWL66 zm?kK?&9-LUTD$U^753aSI~X*LHSRisomqyG(QV@ybRDz7`;h0QT06W4=Q3iURKW`W zEZ=$X*Z*uc-|`FgM|dzw8YtDoct?ssX4v%J7*>q1bK>#mm(ZsSI1B4Z1m)V*t8Crc zHMRvXh)9y{_^0fE(sc*nx1~It^5#f7C!G(WlUanqMz9b|D~{W`8?Li0Pi(|$qTrT^ zKS{eAE|}wRYCNkQlDxOvyaLP1%dz|Jx|EC_N{dUEb*KiLwCqg%Gytc>Ytyx2}%+mDTQ=_kOU_NUzy9h@ZW{NNa~?vN`OvXlWVYde z6F#Y`ChR$jn!0d109Zp=2^IHa_G0L=_y~;-kxvcB%#0?yq&7_HSdn$dG;W+b1=A6D z`JEJ92Ot#Y&YNwYe(*lyLynaA@I~MJhQ0ITQxv3Akd0+Le>&a1s}2#CB3wkhTM!_W zB?Z}5$Q*fk<5rt{&AIkd!n3Ui{kvX!nY?VD9Vbj%L}S*Q)?e?6W*f;7-Sp^oI|TDd z7|{Hi?tRGGI@_!in0oqG*4bd;5__94+*CJY&dUFVq`2H{1!TpYVKE@_K;U6@$0jAx zcpJh3LerB0u$O2|m_q`i)V8CnlIPMIk?!L05Mak?bs`iD{VtHe%hO}Y zKl#vWjiP4+BGpjPgk@SC$jlJtkl^xBApBZ6&Jcn#1^&=hny41ncffoS0{S(^hA>XX z5b#4aCvE@MKVX;?+3hPYwwK>|!cv%js)=*7S_rOD6rTi{3@2p+ncm1@MvWRg0W3Ti zaqS>FtLtcO6c7tgIEr~f7>w~yJ)3|QJ}C86(3jyDaZBhr5k*KefK-Fp;B?V0sTBy# z9zwe1LsQ=3Wug-b!G#kZo2c4vOU|8baV$iCP{+kb_G669wZ|WSl-65w9R*=wVWF$3 zb@!9~#H!+mnekx8K|&6*{<~Q!{e9zhxS28Z?X_!Xr&;PaN}rsYheCfDQ8mpqR+y4% z``V!)qwBy+$2%-#F13^)c$I`-!ys#z!`$Ug;G@_aDN8UWWkb8>_z zK#WZhqMe3UlpxY`?qMA4EmIV(pACt?@Kil>deo{(uav?0T21GNA-ug|Nb$#3)btmj@>h$e0F!79UpMJ4!IHXsq$k2l!a> zmAS0-DcpoRPvj$OZkV@vSkr`HI0`TRi<`vV7klI0DaI_z&^s=2s3-BJHoKhOs%x*+ zC~@z(xh#Iwv553o9C|0 zrR*HYiqEsLDEDC@|FaGH_qH)@#F zIM$bZgwGgV0%(8Y0UY6va$dLktG0dncH6pXGkxWT2oVCzVUjv1FB8Zm7n#^apckd& zL=L<9+ST^rb1!moOgzx2TV8tKx+9b9V)9>;gwsY@OyJGk<1hv18y@&)+qh|qccS89 zUUu6CTXxsOu*od8>0erH*Z*~sJ-4sK&b#?OONK}ElVer%1U$z6{63yq6XB*NAmSYn zX?A45V@K)EJ#)#~mY9=|U?(h?oar?(bbk;w0tpS_fg!tHTa^hEa6Ns;eDO-M_>SA~ zYJ5>pV!QI?x5$EJD{Z2#|W_>8!IfvUCfRLanW$!eB-te1t$I zJe-?7-F|xCoz`{aBb!FPDLrV+Ui{rZ!>F>$&Yd?4A z{j}6+;C^(GGc0NDwxoi2R>j5cEw3T8MADvlI7m1wFe=_!L4=NlU<5FS!>|bw2t9_Q zh|~nMiqZz5h}G@BuI#vLb2LR*ZkWdi_cDsGT@ZYZf~pH(qnwPoW(P-3vu+TQ(L^ zP%`Qs;PP)W$e3%WQ9^KDPh4OQ)wK31-mY{n% zZ#78`jwE7(Aqx%MB*<)eHV*7Tv>=WCZP5^f2a^Mv#B1rJf%3M!<<{gO&&m0U@-G}^ zolDN|EOK+Xp;HzKpv;HslL0EQO*`|WY>bK3Z>wF=9Gl8xgWtErCKXZl;loOc-jh z*%70*B!O<@vA&iz(P@$W4F)`i^ae5tnIZ#DY)u+txp$IwdhNs7aRNq4hSy5eDJ3Uw zP~PDrM*Nt(LyZ^mLhZOZ@b1u{PC*8Rg<9r}EN8Tc{Y7=i5rl>OQN{wsc{j$Nq4zNU zzC@Q)O2Tf=2=c*jQ|@bYp^fukMVga()Ur}-dqt_6A5WPZFCfbu^r zI#2z`f9i=V{GxA!vsiT8fA{bqWFn7S+xBhS5C%TBX7xIzzQP*bP0!jz^WgO6ty2BsST1#F`E%y8r_PMC5RgSD!}BB)Nmnt6^`-f{V$D@pu#`g-m-4nRp4JOa z>0Y(sDz1e%KEI}k=R@46^hk*X@$ffgk84Ac($`ybK7l;MvT}Xmgi`gbE zHjag3wja<+e0Db7NAT_t7_t__SfF8e6_a?xs!gnFX|rYo$f1^DE10{`u338(EH>o! zYW7=f{a$JS0SmnK93i>=R!HBpe2{pND6c3A;8)E`wXcJSY&`f09!!~aKflG&2~P)r z*KZ*NGyr^m&oPuKLr_Incjg6jn@=jVPw@cK&Rk{wdFRS-6WfkL%pDY!4nq_GzdbyW+%pt)X-&1gd#v7? zCsntEu!Ltao1*PN+TcJ*f^I?K6DFUYn`Z+Q5>HP_W13)zlZOey%kPG6EFvb_d47Hv zbpCkfz7Uunt!=SP5RPZfNWi=EvsQ#s59rMb${F5$;?EXX`iU(KfT84-r$FxRge&V) zEA-Gds*-y{UPj@3rE>&o*F-KpR$@7`=O8aB!{Im+bRHO^Hcb4GqZDa_siY5}zrB61 z#Nsp3?YwiB0{G~#ID}jBV7(pR_&f8dJZP0~JZmT4d)aaW@m}kW+O$b{JMn<~nL8DP z|32xQw1Xqzb^6ebqw#2ERqOlaovQm46f-b=*fI0VQ2gkljY z4z#64vN?d11T5)d{x(O>#QWslLzg8mi9g;-6h_k7B=yb?ruH(BR$b(Geekwad#i2* z>TuCK8DaGSX`qT@U}}N&h;h`p`C|Ae?Z7J=fPc4uzKcsj`|Nv5r(3=+kR-r$5usW; z3f*F~3(YAhqnIWe;s*i1T9h`||4Ik&o=5i%1t@RLd0LFA400ePPFauP@r~nsHDQn* zYiM&M3+gfHhcT2B7es9$A#&y~jyDHIcJl1uH+-Z7-H#$?5wzndF0T+m1#>Mfwk_GF zC=xH7Y{MDRdiG(C`e1~qa7?%g>mNIP$>XNs2zct?bDJIlyK%- zC7_2^+BCIH;3dfFM}_+ovQE~ zMU+HnOpx@39-8;ILWR!lP6?vr42mZL?=6NLX6?QYtqXRVBTxMqv>+UkyIy7y5Q+jg z6-_IuP{K@DFm4hnMKDGvO*laY506D_!ryuc5f)Wc+Z>pKdIkn<+Z#LW${YXD3eLUE z^3GUp!GWxcPR6tHi0!=h=Pu_-7e)H=wSYt(v}O6z`JFyHa}J(7-e*5KuXe(@Euo-n z+s5s9KZNDfxvE4&(U>TNZU##6gFilKE0^Tkl~-JBzxmaDPlpp>45>s4B2NiVIN^N5> zN-~yvJ&#($FbohWQ1L?Usq40Ciq|{jW3rDQQKHC!PMZsNh58p@1Vl) z5&+nB9GBnVUOU2Tosiz+)MTK`J5+Im-jlM^`~THVhQSwln-tLG)TXe7w$I+;rs|$< zBfPn4)hb&Bcw;*`J#p8$P@{5s+W49hxZ{%Ah)BJ5lj78Y#@v3BAk&I$%a%=c-+lMm zJ$QTGO;K$^4Sdzbx3N|=8D#|Nw>8&X;XKc7AC7tV9k<(t`|rkL9;L3Xm{TFVz}!`B zk`m2GAX~rodfS9Y=q?EaW5zdbw;-si`ccR&ct_C`!(RL4?^p@_^aL@FAxCw5B+Q=N z_AuPNKKU*vWAjRDd`-ryrd{{6Ui2UXH$oOK0yr^XUa8m;m+)0dSanX z@Lh3YMzJt^D5#%J8<*}*Y(z}bWd3d>%qCU@h1q~HAdIng2|X2nzN@Bmps5wsiT+l* z===-ph5L0`gx<*WC{!6h&05a%=~hd#)w=N@JVWT2{D-*m0K0z8O29G4tnh^ zFZ|mBi~+_9Xx#)~o~7Urpb|h+jJ@jU_))h_G7l6c^p{70RX;9(7rCK6fHgy`he^(B z(ekCxsV!kXLZFb8ZimV$tmY_`aY-~wC0u!Ih;n{@YaGGv8|Y&>)HKec6_>VshmR96 zU+zM}&+e|&4r%y zl6|YWW~c1%J{4)=SDcBVw2mSJ?(ps(eL73Gf~U86>n3~P*AMWk3V^!6q&K{&-(}NR6r>`iT`1%#Nt-F4R;b`6Vn z4hvSwPPq|X2I9qL&sxA71o{p9-yMYTL_4tMdVl(`g``{gWQ-jE!d^vqFCcpk%rAfg zVl%OpBMGhLFxRlA5LTL?*j^Aob1w8yBOOoslMp-6(2B65C>A#TlXdl$KaYHvo6MX5 z_fQtHSSJMX2_iW(LGCami`-OMHGqjQi%3kg1!pYceBFtYcNAj-NIblc1R&Q@goDZ( zXpBovMjl5OEoyH26~Y#w8ioQ)CqFqa05HZR&2K9XI!`X57X&B#k)e!D$ir z%ER{61vAMnwb-%Ob`XjzvG;eVt}Vdw<}9+^CDnEahWi>`VRrDShQzcmC>$WD#h%lnU86Ae)V!y>JQ z&{`YscaekZ#bfT{dV3I_;drd_ciQo8MUXp&MXrQ@5FsG(M1Df8TPdDZ9WZy+IxIE* zu8mb5gv{e0NXN(*^%6o83N;^|(_uPm z`HJnVY_^G%Y`gHhr1~y8U#cWmSJ5ef?n>Zx`nW-c_0eUiNcWNytm)-J!r~0;bXnhUU+sZ zw`9cDu3AaT;#tRlBxL53Pd>?gCnSd=R;XNvOc!-wfvfIMn{xeoxlYsr-3e%=#Ct=; z)T@VYZVNW_SvbEw_%!Ky*4!q8(xx;%hf zNqX+ELL%C_uO?aWXjh&8Y>@uR}gajch`gW z+Z}*p#49Lf3Z1+Zu8Ug8ip47Jf?BDhsR@g$+X@MR%*;pu-d;yYR~JO$T7nJuIKX5k zvG;jG7MTtv3w9bplYM4VW3>=UD3S?$#AmF|06+*6&he-vM6HGb0E#64lbsrG&D1xFJwk0q#Dm&P>~}Xx?3O!!ZUyjQ9{k01 zHmkqFV#?mPqc^X&<2-Je8)@I0mtdt7?vu2$J8$^~;p1PyzEVIP;eLi<*s{()pAhXL zJKW{518ozwaOJmb#T^gZAKpJe4cnBZEj!EN7B3>?7)I?D9%jr8J1`b+ua|W}Ivfh4 zNQ_kzw5fwQxQB4$2>W&LK4eb_wOE@G4Sf|17Gs2ST_};O6Dh88a#bTCwjWlL=*%>1 zB~YW>uM}wIvI%3w;(c`^WZEeem;m87fzYWYOnbPhmi9npAomDsA;|pTo`k{5A?T)| zwEa<9J{*TSZ=m>ixlFK8##tUTeiXnGJVg|uFGBU5;znzv(?K32(sQC{^y@(pLPIC8 z)kt@fmAv|Vq6G`GNnq7(|LW?9E2S& zn4bX%eGiIVxoH_)3j6g@64Deg!*&luSkVMt+eK^5@|Ib9Y>w@s4_`H1>&pRkmA>_o z`8AYNc#nXjk#H2A=tw^RETrtPv*vuE?3=~8`rH1ZavKOuv;&YcztuctZ=LM6R&vcF zKA}uYA`N)Skh|D4yt=(xerM-ph1;r?=iBp}|K`@(%9U3+5SKp&#NGEk0P6V}j5~kV z9D2*<&0Yh7d!{06<z2ZNZXx3*ptHi0g<(pG2R$C7&qh0k1oFiJJ9F@(+vgjgu*H7b|4Vp3F64bUmWdc zS4{J>*uHu=Y4O}#ss$hoo);s4au14cqDekjUB?7i6x9JO=+9Y#ojL{&5OiA|feoN0xa)xn|1>?#N*k5BiB9~tP6m8m>$yEU&Y}2MqP;qTI^?mP$ zQjX%N^JeroKH(=9>eM^#JYBXC-NKRi|F&Civ2T6rTdtGBBv#r3|MY9S`R1El4Bq2H zUOGo6Ba=iR2tn`lgM$DEe5m(ntA%h`tw3av(q2TJm6^@nd%`)ZpO+T9YM_L66o+Pd zV!YM$4caGV)hsT5ibYX)&MjpEb8H`kvk&`uP-3Y-9#beEsKNRbu%nOuZB4B`cHIqM zx38{SYvI}HmWjY0F8#>DT1qSlvgo?~Z`)Y)0n7CCSQ-F@`eQ)J&zSGnR+i65w6)h< zfTve)aV~!ZVhk_o)u$grI1kwTGtaUSNP?3WEVtbtG7nM{sBQyBjxYDzuUG&I?<0T( z^|0i}lYcCyL;P6MOq(Q>m@@wiOPse1P)n~hv-mpjFh4A7wl?UvQZl9!8l>$I;l*|U z3qlr-VmwS@t&b5h4yMIYKle!YPgVdR@cuG`o*Vx=6nssW+S=7(W1*wtYf zDTyp_%nCwLLK+GRuTr#lKs7>B&dA8LctT~t2-$Iju*jr4dLbIX@=`sTKg!*o<12?F zzDM7vcS1n!Fy%PftWP5K=?|sn)Kky22j$@waWH^ivC{2AK;mrx>Q6_77fX zQh<8wgMkMx&-4KBAd0VY!sd%8#&$*=YebO=dGWeVH&=KTnfNe@b)4{|A$*%bo{lGG z+q8LSLW~?ss5sL`gQ-G_^V zjc37vCHC==3X8~^!}ttZ$&kO*d7>~pU{pcbjoy z`H%Mdf_?5CTwS#O(mj<`>t67*Z432iOo)|Vy_&l(g(SF$EU_Y5BLoZHn`YV+B@ceUoxCw_@A37k zKl|Aa?S`*k=W69-g&ilKr1yP=+H?~_xd%K$e%PO5iK2%WAg4U!cA_W*hD8G*8lRL3 znr;@~;Y+%3A?d(Jj|)+WCGW?%Ws!$U0Kr$%I%IX!%I&AWUIleV=dZbei{!#k=6=+4 zMU%S;Ls({~;5k-SIJmY1NhtRqf?UpFP@y95{^7M(+SVUlXKhbBU_UuC1JvI;b`tNR z{m;L!pncnHb!LFAo|lC;({0ag*<>m}U%P%CaPa_pY#T+Zd z_fLe$WE%MmP;{KDhAlBMnLcg^n7)2Oo{TqEzw&QxJQ*ytXe#QRv?9FN*py6c?+G|k zJ8Tg}!As-(pwfzF3~4Q+@DNILioAvgkG-*}%|1aXH&Z|+u#SiOs~RZc1pEd^VGKeM zCZVu&_);&Z?`S-fAB{*&1iD}6+5<&EEF6lW5WUo~rU7y_>R=E|3#552R~d*P3q`1T z@Sw#q17y?M|9Zdq?%HI9UBx#3?pB0spM#03JH%|1o0~gK0!^Pm@|#>N9uH62n3Dl0 zd4>GE5H9utN!vm*R13lQ0fjoAe-7dDB^HyBYndpDmKGRnQsV6lc)z;#ylT7tMrp^c zR{#+Kdci;p<2wB)eio`(;3ZwV=AnoAzUtaF1_Z=X7hepg=`=?bR@SW=J9>q)pU#7C zx!!Y$cvMLU^&R*Bl!(9&w4iLucEZ^}`B$x3XInRKw=El=CTI7cR+nwrw!?u{jzTc5 z)&<0J@RT3*ALovEFChPkA`b(L22l z?`_07^d< zT@Ik)21MV%O43~UY__m(0QoRMb#x7wS*t>l3U%e}<;PK& zu=4iQcu_5nM6w&M*~G$5PMZm}R2$$GI$~ofpLM|nI$`gHFsVFvn-N@Rn3Q#YA0fvC zYpSgy%!pNw;!sUc@5q#W?ZzAJ>h334g@B_G&O z>0axmR%>p4w#_fhx2l7m+N!T!Z1>&yV{1O}p0yNz>Rr@;Bi`HeG{!?PAO}A?SW=01 z6K-jXX_)%L>y`<5vzR!HTv_PcGp&lk-cQ=7Qv!iHl8{SyFx7<-`vEdkaIe;kE< zqlrFb17Y#JH|$WI%BiH$#Ipe~4!XhwEYLN1P&^7F`hXf7VlhvIMbo{V@Ffyfp)OHW z1q1epz>5l?+eI7nP({$4mDe>o&mfeL(2)asxsP;YP%*B?9B*)xx;bA$TEo1azic^% zNB{`Rco_X77$5rR;UTI8N)H6Zeh9NjkfLKydIcjrR3I-eMx+5v7$bcM1vT!C#d9fvOd+eVu9FFX?$%;>{z|#%M_ow#pqklF#dEA8#6G73%4K^{5z3#h= zFmqi|3XCcy^Jzg87DkAc-*l05O-d9}KcTNd&UaEC9U;B?sUXWZ^HN)S*F!ezrk`MJ zBoJy0x8xZ)D01>v^(U;a3;+x@XG13r+0==nfJ)j35R*4Tu;a5J$Eo?_zDj|(aF@Ji zgl>A_0z1$=JXQrrSagB}S{rZI{{;Pd;wz={KqMb^C3%Ifa&;oo(e129!`nBmwU2K%nIV z0~2d>_Uzf#O~d3slwePH7kM%a5FxDbYI<28_2g%3>+7txhTN~Nh^`W%3KNunMp~K` zk~RpV#3NitSspT+y2$gEc8ytOKMjn@p-;(^m*I$Usyg3;?X+tjkebe8kA9`02GdUCge$(sE zf9v0W`X9g29KZWN-tGUtd&ow0L*ZTB-cixWeC|$rX{U4#2z3(jLx%COFZD&GSi=SM zM9U@lU7{Uil(K-a(v;sLL{-b@ka~Fyd z!6#uWC8Gnf`1Gvq#ct!J7!l-3D$gOJ>$PiF5-Q?+=FYa(wl-^OqCk_pkn;{%5P=IX zwMmGB)qQ%5d`uK^_F0+fz{K$iAVU^E;|LT+slW`x^H@gih_0>{v+x|q4#E&9RhSGdgT35#Z=q*-)wmX$|kSaALsc7!IS{p2i0un58doP1JL zO^uJg70yVr4nj-iLQfhfHH3slVhZ6G!eU-bkFwc`k#?-Q)pd3cOiU*qB!fg_hoOMD zii`=ja>8$&lfiVh#@i)?6~!W-9Uox@L`xF^GxeeLMNB+MeUb{}#gNlSW6^GMMU8`m zq(Y)?fWmVr@P2trCF48UUH!o~LXTW`BcnlYznrpODgwyl)VNH_>A6-DT7&b$R~Z1j#; zZ$e_@Ei$Xns><5U@|Ria#b2^c0d!!C8C2+6=t6{X0QsR2T4a6l#2>A0-%eYcn@9uS zz1B%#`(nxh6oxM+$Ti*!w%xO6rG}n2>D0`^|4G1m(G6<<<86fB3##bIoe>It3og$>Ne?OHNFNnWox? z(&o_uDbNx^XuHGxZYM@Nh(e#DHZq*L%rh_uu!<(={b=n(ICuMUJ)lL^a`0 zZ%%#y0~A&7oHdcXclQB`3JHR#g;ENMBo`jUt3siM1qWCphSvznwjV-)5h63A90y5) z3_yn9?WrUB1O`z+EQSUV$yOAoAFMnK72$8@F?3|*Tt@?_>?CrG>Sb3@SYRhn?h9sS z+3we$x0}{p!_N-T&T6;$^)}I%x6}M%qFkv3N8zL}aEKaBDRP97ukdF8N_4pDunj%? zZ`Qu&721C70vyI1Ls<)^_xBB1#S5;8@BaPW&;9A%{_M4)A*Wt=-2?A;U9It{-#`8N z-;eem|D{{|1>SV|ryedj`+vO^@|IMP>Na_LuysfgN%bh)xOofVAe7GPH7h>L(}~qU zFcxJ3^`GlY#r`fnt?wyEhxg}rJQe@sw+}e#MWJTfhEB*5ktoW$OSnT`3DeZ3G6q@;@nqKVVQHz z0AvvX{nRpkKLTs?0&3YJxyTp`&0TJd!D+U$Y1B$6v>l0?VG%j=?LZTqvJ*0`8Q@DN z-$|K&j+KCz>?2e-ga_C-=4ZQ)opARzH8s^*hsW$lT?^qvI3-ag{KKt7cyQm8Pnrg* zv74HyA+BFcA2Kw8xb85{I})T^05xV^AR@uqK+LRkdJqiq919QU<2PS(wRzKEaY5p^ z(hXJkxhg;QNrLjM53fFy-v|v2MO>{i&FcizeIy&RrL=p;YFyh+H&01U)(SZJz)j}SQ3i5 z#V5)diFh2O^TL5{Kl|$&dnjj!rq3g2WNKm6&L=M~4`Y*t%kZhzf{xWA9=vGPyU$to zmfu_ZWB+6$baIK+Iw0H~hJhSPEoLYnH$5WApQ}rK62T#l)Ng19 zCbUM`pUHk|&D#+;7ggtX?}iQ9gMrlDO)1=f(p$Z1o$WyJO1J4) z_uhS%efjdsZI;RfbO=sHKpKT7eNh1Z2;p?XD>aSPgut*AC21vLnV!Y4vK%3gGsQxC z{)MNk`pu`{x4YZ2I}h8L{w>z}`V&_B=XS%1BXfHFuqO-o8k5br-K7r&luu`v>T{>5FKggyITD z>717caHQ#wElG)@69pa_LTCtsU=n4ir94g^4KhpH-#KV+msjJRVO?_zeek^f@xsKL zBg!tdKZ!ztMw9#W2pOrd)CS5=Koqq|@d3K-PkuHCWflQAL8w)Eay7IoI@;L7Z$X6y z;31wSr9pH97m66nLbwx0kS6zn$Sg>6Tl5&h-x4>UG!Pu@%|&P221`^3L-3wr<{naX4nz0-_RX6RVFJ zJ$P$3Z^W<}wd=lilYLrLVF$`;NKfH;a#te4AZj3|i-2GZAzOeNtqLZZc?%Y>)`soE ze4q}{~0NC?>6NXso zS%9!8QU_722EbDoG$lulS{eCDd1=KczWX2iHId;_Yd?nK>Te`*+d@mPHp`?8D3f+x zSwl4xjMJxcw8;|sF`lR&OdE!3542}8Mdj4FaIcY%gr%jPgjUz7>7ilx`^Gz`-f+Xi z2d7qqdzOTBuO)X+$zHFFK6M0rczUPPUp)2Ef947I;)}lN?w#8HZ*Sn|_B*}*sb>j^ z?c1Mm9Sy|DvSY^%uNQ|RQ7%B1n(_hq`}C&wyaTRhCJ2_b5TQqye2U>e$OQbwFaMVl zMqZ`m{iX_H<%M{s#iXqPEh^MoQIR*Ks=dYtaoqo_2kowV?;&wKVaLj7x=G!QKRxdP z2<2s^B$#hgnFY1Nc0itGkaimrydML)O}Qe$p6AS&W5*!YJtsfi4uXQbATPxdu@<#kaw&E z@KG}WyF)s866Bj7p<01GMp+~(1qedu(YDhL*SF%majpmg4~5*mcxJ8vE@9nBa-yv$ zo-Poly$G!VKp}nziU4x1yWZPrD=t0PA>sV|2-~1HeDOM_*k=fCL=WJClv#Licz;pw z2}Xj_Y(eOHP<-+}CQ)SSG97_lN+&E-*WBzlDTS8xpgcjRSU<$kp7a!$XDE~=1Q$z~ z%&40Ri$$3OcJRTQ>Bn1$MVK|!SJ|Jx_Z=(5qw)md9Uw>p>0VIr;Ttye;hP9OLW|s+ zbUdq36oL>GYSM|3>9%v|dhYd&+vA3)9YWazG{k6C8Kl+B3_v=k73e|!275E%y?peKkB zDv%6!I$WX4KS>m79tX;^<-frp+F8knz(es%re#ocrqxj6SkJl;%ZMT(3h%K{7+=0a z_&pqf-&=mbI(EH=M)!Iaffx^3##$ln2YI0=jcB#Dutrxjq`d5_H}YBHbnz;V(9pTZ-$=7xW;zx*HUy$5`h_m%H`MleY>bT^JL|-~ zVq-w`A`l3H5J;$Zjb`Tk{?4NT;w1NdcOCnFK6`m!G&9dU<^P=j`JZ0i+CmPi1Wf{F zn3oEwzU(71vmc*nE)l5X3xNY#Y-MK5jy3F~jw&6?$5oi}^5#~Sd8hFy6oD?Blx^z{ zs-PMzhhVfyD(}Svo`KJ857v;zb=&Ql`KQqbj|x!C)lLFxW=yHF987tm5k{tv0uUyB zXDjPvpO>{mz)}P+YcC~>P6b$`64ZF@z(*gU%XPc2tvmO`861#NiAJ{*xdc`)cehwfa`iNVI31N9~04qry zAx(iZAf3}Htqa4aEk<`@<9F>zl0TFK(Y)WZ9VfxZKYZw@-?sllhyAv%zdEkpcGRi; zzZC-V*J;xtc>M98;Pj$Ji(J#wJ~1|#tF(#XX`jBU3WerQ(z6gLCdVKMp`d~7JGN21 z{om|?2OsialaRz=epcR39KtR0q@?kgGv{E=oI&-LM_pPEq;c*AF@)mUJ-6LuH!WF; zx%G0J)KzOc?^t4+zj1|qF|E<653aX$x8g&)?It^T+x2$%&g*R3oi|zgjtzFx;u~$* zvK4msUH6iMmtubd^Q|GO@`DYV(Ubx`bpVZI>ik(Gzh7>5-0>|m9|g%95pOr!79uI{ zx%+mU_7N+YJ6W!hzetW=1I`b}Osv3;$ z--U1wBTa|s`?ikc<4r`Cj>EkC#p&a0(b-d+u`BUBhR-iTG-MCVd)vVy&d|2s|EG57 zn^)N92RB*EitkuI8aNe}d2SdfpzweP7=m|XNhC}&A`m1=sEd*m3kr_PX23G z@SN2V!p;R`%2ZL|E-~e_LLO=~uTlyZjJ4FsXW8(?1-1{Sw`VxtnmYRI^x`m`xZCZ_ zp56Avd?E&^-MVk%ZlVIWqCJ3z5JH(Pg~FhuZz%{dx=$LKluUQSXl`M&@C1yFLbW^bA zv`Y1?&p^C~uw{Se+xLk-*ll;*4g(F_b&C;HpI(h`j{vg!@3(KUzk2Fan>J%Qt*n;V zH*dS$CQqC0mVz*IBLTL9iZ~j-QV+WEsUA3tW`uAxs)PzV%*X8M)2+C$2y03;xSMV* z2v%{JMDu}KI;GP>2#qt1F)1>e2}9^2FEN@!7mX0>0~0;Zxn*08O`bXdW(myDX0yqy zoSHFgbJ6rvH!}zAITin5IGra(w8h;Y-+l0YGD7-Y<5nxOxpQZdjFI?^qZJo@?A_%=lFS;{-8Q69>@>0L7OzB2rF|}?QYN0yZ7FE*%|l}bgpQICQSrm z3HNxCRz|`hF&lMb@LzR17QPly&4!IOZ|Wp#c>iUHZ?pZ~eSc|fHLuvw4X;x>v5l(a zO}^hc_duMQ>_Vcswr#2*wSfk>m{Mfk+PZ10oqopI&J1FhzGMb1r+?d(H{4|3x$k~A z+k8M2y^Hy5Iti?!J<^WW9-H&|MfUpkeHNz-SCl{m#ft4|AFws=ZlaY9 zrY;ChI%S#;~h)z!9u2(~!)RZg8MRdka8 zr%E0&S7x8}DX&v0ZMl%vL-H}nr=TDq#pCv&h4)cXN=MGPOB$N&UFCfFeowBr!OhT2+taoLZp>4R5o6ghDvlnW(kd66p za^`?l#*Ww((JfredL0kxv;Y7=07*naRH;9^0tN&AVS3eZsc30#q2hiqnVyxm zrctq9iQSBxetv}RQ%w7kAN-((Gv&J_NU0E;PQz^0{_6AA@Y=IB zBoiDZxnvejLF&+2@YM#hSBX5`NwqMwUoS1!l`EgLpa1+tT3X$Q&^X(cya-_Z;8k)7M%oDk{Pc2^^X0bTljVge#)>_1>l? zQwM<^^wq0D_)}>&)z(x&32B-#^hJ;J+F+wTAZ zF1f>)v=COVTZQIC|Bza@nVu6T(K5)-%_Shp2+ss+heIT=7YO~NH@4n|=ntw)Z3prylPmVwR zV!QGye`?>o>$}jZJp4L^_SW`;cGZnvv(?Y8;r940A?~vUtt{ z`yRF}|MstT2@P*s<$<+!^!XoI_lr+3!JHG25Q0obf;_mJf-VMNtpgDJ zG%Di{Gk%$w1f8(7 zJ84=HBJe53iRO%Bi;n=qG_?92{NINNblOQF`A7C6a2`t7e()}Z`mmQ@cLO*=P#g0# zeaa+C7v3kbC#Hhae~6JMd#FodkP|_5uLz5B>|f%Bm3PwM={mZ@%dQ|A#j{ z(y8quLO=}d!*zJC6Q?X;ad?l;XcC*1fKb!{DBzkri7EO_1*72 z;0swfeM*?U|9;Fax8D|A(ib+D0TC5Fs64KlalqqFa_Lp3g?sM)w)^{b)$XlaRKIsG7x9*Z~X^XGB9>THHR<8OPC9lLt6v)9v6?B0AY6x>y zgvC3Vo?#V)qqkF;Vi#rx+rkK9cMhP%8X?)AXT~8e5Bph9%%8X%jOQsBB45@ zBQ1=^%z5FQsWzX*ItyVSP9$Fo&is&fyUy?x7y@=Sak7a zLquGlbrGbpb?atYL#?pok32$y;;X^8N0~dB6$x4p!D9<)92y`LR171|JR}fWRA=-U zK`%ytQWHe@XeLpO^oonp?LcMmxCH!}Nz!4XG2|98JB9{YOh;GU=BapCL1^p3xmJ`AG*kdH6|ILV?c!yV9 zxtgN!|9smWn4}TLP+QaqUE1*|{Bc^#g1ffXPBhH|(h?@qka*l=tC(1AT^-%F53RA2 z`liRw{Ob1ZwXw8hYS^;TW{fStA3X-Vf$52vYh0`i)z)kwzqEH0K0*o_Y@yyO{SJ6G zgg1P3J8*eS!`D_o5Y(d6=$t{xvJ$jB)yPaE;3@?|qV`gYq7(>d zjOW<)-VED0m}jr9KJv&V(=UpDtfz z8#nLfXz~joV$ud<5Lgwv76F^JaIQVP>S=2#sj}CGMj`os6%F8ztniC}X!&3K1FI{W zZ?9pUG>F(V!tqtr{)xw=?GfmK??~OMGkrBc3guwuzHuDoRTQOe!+e_w(HO@5pM!Lo zrsJq);gku@Bu;RG;1(y5w|0<(?rwU}MJeq?`yy!&8E7=U2M<`y>u=cG@2n+~lQKtW z4QjgC&mz>n6s|jjb~}M^YynykbY;1zR!nSnHvY&o;3bn7$!(Z{h}wkU$Y+>K%ayJ! z2pRJbhC%9NDcTZFhWQ>TEw`Pt2@-)HO_Al#6b{&unWNA)AzMh*V)Ck^+D-sNGaa~p zxcV3N++(Y)3~j9%)8xc%%vL=ORT3xAZxsrgKh?qDj-l{v{K zFZwH+{=iBr`Qsm0*5zNbj?!w*k6AvxnzIPXJf|#f<%vc+w=`xKkwXip21_qLAWv|X${R=!b&=2x!QjGkZrx^Pt3^uN|7eZCUc*(3B6cd&g@cwLI5cR zj4>XL@fTx~j2S{ZkszQmZoBPPXK;)0noWyOfHeg^xgRDytUEKdDV zgq$tWeA|^$L^qYwsnWyo5;$SHikNlYB(lPIRO!bTk1!0{6EF`<*4hi~eZKgt4OG=* z1RI|}ylK~O*!|(de&^qlL;9Ux`2Us*O1n$u>FKjfS9;f`#VhSho1!U`j8Rfy(!{B0 z_X_8rPZ9xyUqUF=)C`s{J;aEZTlLgxd*Gq(p<&QwX5)H}36M<8PQDpwYu8>&Y6N)s z6vu*tzRjIK$E!rFSh>QUe)?&voI1nG7hFIYsIm4ZfB$2<|H)t2&U!+q)5k$v#@S0d z8twBpebw%||9g2qbE(X?A%fKDOf~MryK}XE&&;1 zLcNwt4p4%mSoMGF!-U$y!c2kqBzRbOnl)l}Izr|B3~C7OI@D;*_yd)O;3cvEP+U?d zL_%TZS(IJM#{5!3ZBR9(RN}Av5DB!oRMH^gNENCqqSSzNC5+SeOa>kGsLR2RkprPs zjH7&vhsd+qbF>8wIAY_G+!s(rtQhSrgIu!+Oe0N%0NCZyn6~5CQD<7#u;1SQ&Nm1W z`U^|h{;s8xLa?2@Cl3fv(QZ)-m>e}`JjyeKhNHO@UM09@D$Gr=)L}s`XTVtWdw>g! z-6<9C93wN7%&bueSOS3rs*D-26q;5uZ4?~9gQH624oAi#uW<^YGaet2LsY8TbI$1(e%ey= zizwxqk2O9hOV-ogNt{u$9oxT~jvia_)xwxCiTWht3sdW)VHjI06^61V&$Ff9yvHj5 zEqi)s8f`w6DArV-XBh2H^umP!7d&`) zEJ|KEhd`mN?L+q5jze_*7-Q=xv)4_K*m$Ck;phR-FtK_$F-{AtRKhHT2nmuSu+;2o zE*u~E?6=W(5i;I&Sn?%o@a@Eo;QJ@^7i>7SeG~}zq8zzE@^kV%d0lCG+LFVz*+XPh8bm>op^z>(hJ3umOI+fAjGzG# z0>2LL*Ic{ER<2kE4kt)7o@kFe`*Zufzk1Lv{>L@8tdYBa>P9R0GRtud+o`4nBckn&#vTm<$h`tW04UtU~<08CHk0P zFH!?chVfzcE9!FcIc76IYj)XJE%Q(AwmQnJb&+3}LeyxUf?qHVXJDG0S%MVbT5k=F zhivPib~_R&u~l@HPze8;`@d=D_&v0S=JQwQZN5k*$N=e}Iy2Q6g+piQtF=H~CW4EhBXj?_o20!~Q10M6=Uhj z(PC?eT$Mn#???+B?T5j^Zg7;mIqth~OpaYRvCzij?~7oHl}S_M*T;T7r%s$p{m@cd z^ZrI#iLffadM&{)!p9xphy1l$wtavdg~rB1%~k>)Riwu$vqpbCo+V8|X2KI(5{lYH z3gh}RL856hL#W_%*~w(_Z;vuLo@R5F1T<`jj7yOb%nImBm7xrK=Cj3YGU=4M+#el}x55>=Qq@E4JjkTEQ29EK5A zlTaAkAY%??;E{r0XDHxD+7!n~BUNd#?W7EJLFDAin~e|aude$7c~;yXpPO>ST&Dcv)*ER-m%mJG&BvhS#;++*7Mpk*7nXXnN$KSh;R#&h@FS_ zq}qyl3MDx^B@iWHyfWhj)j}W{(vlh12sR+_pbg0s1`&2b4*uwzRET7s?A}5u;E02f z@lhNce8{YtWvAcr4XeE6>sCgA?ZV1wPPo&VlZ6vXY&y}TiFT^yLlxTg?XgnQL_Tx+ z0xK&nwDt~q(?J-YShk$;_gZn+LEHU{r)-e?z$I7}Ry_98fQA7=;jo6I@dPgsTv9|T zrdbP>{R>>^k~)p3T1P*p&T@XNIb34hEHA`0ea1QdGm_5S34*uG^yw7y;2 zd_G+;5aSc!^e=iB;6C*7-`PDfmfuA11Vcq6i!UqSOzZ0*tQlIj_uX?ZOwR1W>z0By zj8FGsZR)q)ZXy;zEc9yjgA-_g?f7!veCt)og>(gJvI7lumXnulWmBdS<(g?ZV+mfF zFwq7P{xYb*Q!$=Kv7HD&eXmP@;HDP;vpkam{TuN3oyfl zRm~6|rc9qfFv3idV()h1tRlhRdhmbP_wM@#n~(Xi6%Aw4a)?oS1w@XMSf!bBrrWp$ z7u)~5^)DghNXwXF7SKd8ReoSrI2`g!{wi~ zy}Nh8th8W6c<~J>l%M2gyjqwE(Pd;V9jHAX4*AU=*cJ zV-Go0itLHQNWF?Z;-rEG`r$nNm^8DHVzbcvVrXm_X<3tmi}RA>UQvE=2!Q&PaVVYmt;;EQc07321M9^!mVm&#jH zA}|EHf#*D!USx;KN$f!z$?c^=NlKs1LI@Z)b1Z=vlzZFLY^BU;8P)x(#+6yLt-+cO zzGg>j4_INvJOXYK*0yc8O`S5!W{n$X=hN_YqfEh!dnZ9q;;}*#G3Hb;1w9dX5fN@v zgS3x`!!7;!HZ*0TxBpS+?;&6>?jWHFaReboRu583;D0G3_-A59&L)!gFu_1ZfdoCT z!$C-@Eugl+X9S!iK^0ny@gCn8gS<}qT_jrLk}p%0b+o?xJg%j8b>t8|f8c=!?D5Bz z+s~IjZljluvD`DJ`q`?5t8wIk7b&!w@>XEXK@_}g>S(v>;!$+X7;gh@$86E*b6lu8 zaJb3wDM3!;AQf72vNI@n(19;CWPA3}&M70`igI&pGeXcHX(95lC$K#9$QqJfV3R&~ ztyL7pZ6y|jCx7r=n@w<*y499N`d6PZtF2>BJ3%1TvKhauHO+cA zDsf#c#_qmBm>p)N?qgOpxytr8HsbGt3_wVu1R11K%|a1+VkCnw$IMa1*3i<*bHgAZ zu0?(AR{!SPHf7OLYoc^ZH~CHqHyz}f%{`q~3T#?iTkV-g{*}Vb16KYe!no$_`{w6cEK)vbFeu)MTB_;f4R1Q@*^0Bm>q#W2nJfKdJZvcRsWFy_~ozM zY=5`%1v^5XTH5KK2Y0C8LkEjt3X*q_UnhK3*A!hv!edTWo>ecHX8ZTRs1BVF#N;$|2r|2gD-MzhQD^N&MVghogz zSCToU?@}djA|PwNo!Nm;!3KndzYbrY5nYz;1jPMk?K=KJUp~3*6vO+3V4c+Tw3uWz zQ7H5kS6)SM38q4Y`?^-ff*10@u-sPWgfKy))N8Ef{ST}TXSxKmsF0TWls&wLMb727048U?kCAQn&u|T zetc_m(?Ns8CqUF-2+ivCfBAcxcGI=w71hH`vdBq7>c*6ringLWLYYlOgtV1Un&^I< zAzJ0+!9XTalB}~Z%?`E`H3_2*DUd)*3I?G>?=(zfxtL&7Rj?n;L2|Dr@?-uKLwDek zfEy-4tpyFTmli>+VjG{Cumzd@_WOT+rPU3D?HAh*Sucbu&iJ$?GIA*4L_fRwBX$5r zWBYel6X*3pjOL$ynho~$*na#f-3K5>^_w^W!XO_L@JOHuOWQ$pVVopTGr?j`ecH!d z$xpZB`fKe;1R1{i)Wg5v<6+ymeTOZWJrnH_X2-cA5}tMQH%IXdswYRB;62=Th_=lY~ew3Y6P-$;; z=2F$=DAB0|FKyX{Mz_`SDR&jee^$HZVSI|!*2J?cTUTr6e(LkK864TYbw5x7>S)gj zB2otg`H)c?t>Ttj?QgfY*_a0(wnScuH8acvemI%`WRg{$n3{&hz&kN-Z7JY)K8&?_ z=SI54zG+=Cv^)HY^06wOMGs0IJwi~hT!K9uq7Ne*{QbnnIbv$sM0))a{teu7p%M#( zO!aIs9lMYUZg1bU)4oZR=GXt>VXGTG-`=Gdb2=LG5Y_^@C!}dcm`e#J!dv;@+Js~06|IYrhG{;3b28U)M2 zhc|ZSksev^U523-{vj4**1|2C9{gLAh1<&4k927LK@!qS(E7; zFw-8t^Xu$Op^;}m+`mMgTgvQ(_72)v2hoIvnNcRR6zqd>h(!wKk+$w;0ui_lcKTcI zx}Wpu6iqKMA*+zwL)ckVA|7s5Qs4&W$*9yVlBV+}&bEnVL}7xeOMdjE4ds<$?jR%^ z;;OLcUi>^cRBq2CZJ>VBdMl$UM8>#@6vL&kF21+{ML&w5h}c6U68emPQJt~-iL~sa zr`ed%Mda79fFwb(#Yqjwq|8=Id!HR_IOu{vF+?Gg)Pb>>Ab+`KpJfz`f#~R1&S9ZK zwcvST@;pDpHb0jx0~G5`Aq-s6Z_-}}U;=Ucj`C~v6G$S4l@6>GX_GudN2IVPY?s6UM#ym8UpXgW?$G5~Ci& zicpJjug#^JM}#pt9&jx;)rvcDobux&*YKb3T!PzZOGfBQQ}@rTR4ITGnEY8erU&LS zEbSdra*!wpZgBn)r1IvBKCgR34fN{+rTCRrbQ` zKerk4&$L$BEJc{l2!SHoHonJA2kk41ud$ias~A+&t|7nkU)DTl`KMh1BccV;G5k-m zKN8KSh+bE_(8ztTY09q~OI|rOQxU3oJRTI$gZi7P1Pl#g6-b5fYR;v#DPTobiEIdJ zF&c5Rf_nyesj>&pFBxHoF(kJn%}jnzzB?_}&2#|FDA)omQ0B~l1PlKD9|jPtPic%= zr_#7R`jyWLPWi#Dx0!wEt5$N!V&qWfR@ymQQ5<}Z!sx`1)NNj6z2XR7sYJp~nm!Ae zl*Dssiz1a0u{bP7>tz4IJDL zOhuOvv`(gJg7t6Qfb_^D9Y4fBAZU#22n^r9@#K$XCr^25`?w*XMUzZjkYuPxKyA;g ze!<57;k`ET!dpN%v??^LG{WK$w=j_*Ad@*Bi}Vv*(rh;M46_4U(Y#t+JM2UwcwzZ6 ztNhdNI}wyrrT~R_Hz(pBh$~kJtt?DCmmBW;TU+y!2kgt2e}*dQn;p6PS+du315G(=apj5-C?)QE9K!t53pjCWzkOHAovCe0Y$IEX3=%XU(;YL))m9LRk7= z{E@BQz8^+JTNbn|_4EU+AyTRYf;owGl7iV$!3$FRB4B(LLmo%vi739kcKmbBbhFUR z@P+js*p1h}(Ud42f>~uEadx!#P^p4WdT52x5LDfrmF`K{^8G~7F!D-rtpknAL%T5r z6%s|*cA(zQKks7ORNqK%wG#64Sky86UND;k8ZOBQR@2aG?>@iAj_f&L)2_LJbO{(4 zcGWod%EkQFx8r@QQ<35Z#zoKubVJnF4t%iIZocWu_8NgGvhk>D{V?gSgdcmRW8UZ$LVE;x{BKibwz7<(p+qs11ErE_~Io6huTw1oGo*;+3(5GR&q!|z!R=|mAKR2@ZD z2DQu?q)JOS&4LF*n1Fj5I7bnMY|v$=kuU-gT&)q<0U+1j6NJ?d@&iFGXLkIi<8%$~ zFPa`~+RrXvEq_*WlTac70|fJ3zE%lRDx6Tkxx!~6G^Gi_^w7Jlu$Z!R2xk$PNE!k_ z27=vWS~-Q&25oOkvzy}63H9H!{|Gv8*v_3$YPI$F#OXQN+}LT=r6txu(8|0~`F0wO zh==pX+OzL&0srVHD6YV|R)Gq2S6A>+Ais6e*xu(d~ENi)OdQZoK{~`^h6e zwWn6Cv3u^j-_tDSEqOD=w^P@LRO83rIE@q;=n~ie@wmm6k4)w=N>yolJSId ze$Tdl??(`#QPhyk2e&z1<_*jkYUG#+AxZ(s!`=Pf6HZCCs-4)61lS2-P$6mg0Ma>L zlK&ek@mJ9UtC|vD@9jKf6BnFotw^#;a*ZoM1SX_>!Wd>NnN-s-X;v?~+zFVv8jQ-x zw9)t_4j~~&(33cdfDuB{8zFQpO?(qHxvwJHFwG7FN2NX}f>ov%G155W8g@SykB^jn zgnnz0o?bwhfmRr``C|)g_8Fg}0JWkh=>!2$jmHT0CWk7DhL?`?eT2~QoJ6-B*^arA zvBVG4mPKY>xb)mPr&-;`4=hqwL!Q7|h&z@4AqGJZk2=FKLf8Bt%t+#5cB*L_8xd+m zkJIoUYP$6_NrpA-(V!BtMa0lB_))<+(hMae2%ltr8-n20wpG_&WQc@)8<({8$ciTz^T78`%@RhBpJd|UP0V?K_yS6{-sCXS89 zD@|BTgA#6q7hPsm=U#%Dx|l$!4E%_tE+hrC5feI^h60?_-baK_3`q4QReT|x8j)T5 z5y;+r&e{hNcF;~GZHeeQOpqR2dlSZ?NV9@&z|B;QAV(7h#< zC}l@{&fNk!mwWmSNi4iH&LolM<}B@CEDBfvS3s!0k(N44s*7YA;XqeMr?qz;wBjuA zeZm;qx@$MX&9=gl63ZJ6Ji3n2J1@(M^ASq8Xkb`eO`j*xTOjem?Rkz-dcRnE9jDdI1;iNT6HtYO6sbny1Q4t*U9$*t2$5QkL3Hp} z>0n=YlKzo8-P{GUOObTSK2?|)CLkfVdWy}w@FIH}AH<^NuiN{(>MXTlHl4VoL*V;@ zK+ejETHU%goR~+ruLy8HNz^h4rVzCkC)h=%&orXZVpP0P!4C$eCrOb=;#w9l#yt$9*t5OHOMgX398V|GR8f;d5FMxGJiGM59*A7dr!GeN z2UeIrdr6|Lm^jf6)E@*4REK~#sY$CeQl*5ePT(+%xL*td=l<41-Q25ypfW9!+{+2fN3gn;Pd4nDiH_pJjsQA=7jTdUs~k)< z3Raa8W{;Ug@Zs1fa1QdQfTiquGGCKGuWs~R;bM}wdl5+J_s2a$FmE-B6>LWLx7ZmK z<#zBuqaA~>m2&_2RkN+BzMd)|jTWLSd~M@V8&^?jTddslnFL|ZkeY_ zP)=YCKZ8i0X>0^7rJse$z#{wkAUST5#8JgU&*O62aqtM| zW8uKhR#8epfX*R0r=wYkK)9!s=K@zdqGZ2P6=n3~(UxDDX%DaXiM{wF{r#@L2LIX+ zl~@+Sq*84I#TcGhxts?J*(?A01N-{l{fIQ64BLYVxmyx94AmF9n7h7f-OFSwi3G-` zzMm0rPN_(;5@b!Bj)t!X7kr^nKul{}8k)#m()X^ltizlZ3TA@2@L#v|pOWVXKe6i* z+fFgOj|gf_yyn+u^WE!HBngLZ1IR*ic&nsze zSp+fD#y>+E%pm!i`;D%$ zJ_0tvm|BK77nd20u^a7A7hl0WQwb>95G-JxOiujcCLV4w1Q9AgI|}z}+^#l#7j&cHVlqd!|J%*~K?VW;dtRJ`~A0Adb?Ny=m?b8^Re zA{D>=4f~-?%D^=Zrlk4MY*MX-rNh9z(>_=SMzAoh|0Tn=}{o zGMq{AVuvxi5$*$iA_{_byP5Fv(=WTuK2YEg+Ffd8wT+!P8DS<&16<64{L51G9R9~K z<0@@8Ve+}aF_#{Oh0y|wp+!$R?<_8bSsh&KgJG7y`06_cZG7cqYB`R!`VU?w1RaaP zz8&^^H(gEHvaME0ea)Gq!aTCW6G;+-^41jx_11qs&T7BMgL^#Wo_#`oi_54d=~Th*WI|- z2#kf<0dz<9>+KWTPBFZX1ZXW}$@{@1YZ`sdwFBayO)N)JjR+H{|3s^JI$DM;s|Y2P!3^ICZxqP7XI#vjN+8mPn1^ZHAa zNp1bmcUAFgK{2fS`6?nE%J4giPxTt)L zfH?!0w+4O3+kmSElffhX5t}|f)%h3NU|IziIvw73^E+Xq{pT@ zhr`kW*(CMqe3|NYY}#fE2t3-pV>>>r059}cX#~;~VlXJpwO;b;`4Pe)=CvL8S6zIi z^`BQ@9cbD;FwH&!lhO#DiRBksZu@?lUtVfe6_c&@@G(1zX*wN^O_6(92wGXx^z5L& z+6#59mPW~|RQzh`ZVJZVN$}0tv_4w*+G7y0wN_49xL*7_JDLaVSovw>Q%Ox@ z!H;|X42=$aAuQdKqlFjJ+yn-OD!g?~l;_p%xSiPm9GN)CZ#8MYr#sVQ?cX5~>7NPi7& zE`=10g%#xP(XG7cSdSIb`6C^5sG@|HRWy5@N&a3PDKD*QwCibZg&8T{SS-b{2}KQN z$NK06XH!Y-*iWiMyDB#j2zKq4e;?~|hh4hp8he!D0IQx{>B4FZM)}Y~-?u;i?|;p_ zAXwLLu=j3TYFU_`vuB)d+0!quHZg8u2t;y*5Mo0LLIOv;umJ&RGQTHOV^#qx9E)TN zOn?g$qSi>k`~xh(kXN$KrrJOS*uk-WQ1H7z$|EIr@#T}-G_R+&|11QYcxjdR{Qb%V zYJT;L7L7j3!5z#wD2(W%K3dY$Qru)Ua**Djk|`ocvXygvB^|47qd# zMDL~Z{DWLa3n~uLT)X=)@Pql_P_Lw`_MD<&TX6Zswi7d@^^&87Mj7WBr0vSc!l}?r z7?Kt*8Xvg>w)(Db!r=&_;Mr#_T`H*A2g{c+KAsUc8L&~kOl_Js6$6maK1AO;Z6XLR z$1ssHJImj*XYXFhJr zcGjon*c-3DXp`rjVKsH6SuihM-{_O1HY2-`Qrf1P}`JuiCD2RJtI`%_^>Htr8 z5feZ$KgWp}4&(nTCaJt*poswD1_0e^>0C(vqTsw>Du$;`gjAc}G&cdHwMWqY&u+TD z=8^M-to|T;W?p?)^4jbVQ&1p|;HY_5vU(H^w7XN?Iyjs$x`xi@ewcI$T7N^wF)PFe zURFtqs`hrPoIDi`d(iUBNIM`%D?LyCXgx`a9cVga^Trq0mi6!2^fS-2ZEN3TO-!PE zTrs$-_DV9FGd$*89WP|b!Psbx-I%T`XIk5*zF;{M(AKk4?2d2UYC9=Gs8VUN9I0Z= zvSp8uKfcdtPJ~F^;ZTqDz4Em6y}QoF-aCs_i!$bkq<@&5{PtQyvdl!lL)GHcVoGIy z?*NO6)F8_|7$CTO*UV)C0n24nxfz%)#|xJpH0qHp0BG`?ziZbgy`5rs9|ht*iKsGc zBkR!@ioR$OX(^_I3BxQPxp+k}wJ+cu!Rqo_e=rT=`y7$AoP{RdxmehP2}L3NKYa8V zt6DghJRaJHAZ4Y@o&v#0!+A{9O&M)@q$6zKv5CU6n=nI(VBq{Gkv9fo zi(s12uwzms7*9HqbX1xRqVoXesxZHIvY1DulAJAn5)a};ip3emypaj>${awdC3vHG z(>fS!t`(d$3aK_`)fL6Ic^|0+?}!{7v`}4cG|4lZK8$faoMXc!c92pJ*E)`742qUICk@ z>wp+0o1zP4!V+OmS5Se>xoiSs5a|{i6P2c|$Kh7e&O>OXfz~c9o-6AP~aM4 z9?=C_5r~QtrHg5TL(J{SYVE5t20UrZ|{04Xl$}`&bieNZdqqneBn!0x38Wt z5bjR%-^3M*88<;eLShkR=UTvsf$O8A6ogk5Uz9W+Y$q|mjl#=2YzQR z)2P>(1EI|BImT0ix3MN8mXPiXfN-k;tE>aM9Q{}D;;gSkG9$5imCRq^)K55(vt4|>%X*P1i)Od^pCA-MzQUr z4`mZUUm+|sUS)^5cL7OJs+dQ6=}&p~6*pNQGTm2i{Uh=wx9}VwCC}q6x;Ct*#_2YY z6H?EZ1z*jxqMMEG9;%<(i#dDTS0{Ho#zfe#c2`Wyx8#(&l!4n_a)iT^pp@O~E{KQWUhuBO$( zeg$M`f<^2cAw)nW7J_`v09oB(m)dj@z0jCI5)okGrb>84Fl|KX6V{P4*7|8E+9#?D z;)l?Dq)H^vN-_z*%WQA9AKm%q6eB)t3+K*me$kn+oyoNJFB;65-AP?`qeftDxg zB^!O3@^H9@lFs`XWO^nY1qkP#Jhs>xYmY+wVO%gKwW$gB_gc%kw<*Akl()amtok(9 z#=>f4!-(T7+9-=rxqK;@L2@yf_8Tdn0qPtU6Xm!4-fy9xv~Urg8HOqnoPt)BPDPe15rL6(0!@?Cwvkx~zVS0mQ2hai zfsb4%5>{mP2{v{>7&C~B6cO31tv*DagGCwebWWl^o=|4FA&~* z=STP>pPd-oi7jAu`X20M!rZLSag2$nbd!HfOaUBMNA?)_5d)qI@<>NJE*?d%JQ(1s zZ@xomGy;aGs#06Gi&PE;aZ%2#yxfj79JH>U9!#Gtn58G#bQ-#zHf1v1MsBcUX!eKD zu=XFogbZ#8o)WC$H0;$J#OWv^hChIRtq(lfe6Zfy_B1-Y6uo@SHP>-a!aKIRpd!th zIa743M}4A=C5F1K?v*tbnLOX}%d5RGK$`-(xQ`-@mHaO2hg=FWEp+mn{nYl95Tf*& zA#y-FDg3S6Jq05%IPSqbyUmhei%x+Y67#u&IQ%R~sFp^EvSR}HmJCY(rtFK!K zO<)jak;X!hX=4atqDU%TuAdw$Rc#;K{+=}qwOGT>_qiuOP$tM`Uu0vxdLOKgMdFN2 z3>ZSDv9pjxxR!qZdn~R4wvEe4vMZpeWIokMQngwz$;lUx#z3>lAL=ALKUVvW6LKgg zn#O?Tu^{sp*Rif6-kde8XTh}7O~jf}iYcaqKQUHG$Fvwa$_TlZ2rK{qKmbWZK~(nd zZ^TbQ+5we3F2bZ!*wt?T?eTvi;W%WE)=}Qe?PtIP3Y*F}2YO&SFzsg26LJZbaaEvx zn>D@kIJG#r2hof37Z3nK6kyGIs?tClXq3l2F?))15$vM4GIeW^)cgCle3c6MD|}&U zP3xtp&@0a3<*U^aWHS{aq?R#acCs`F8al8A@bcTqv?XnX3;D^S^#T3VQfDmNHrce< zQ*HAu0x}qe4t4ECS_ANXW8*eE^Qy1do}nCcaq`iCV*^rsoCwfE4Q-S)OSki~qBf0S zhnm(w+fcKGO8te@nH;i7#hF%_kB<`}Abm`gJyCPWdWc<51CLUPzRkzfozX+zy@CR3 zeS4inH@ppg_1R7Icl&>y`h`_o{nr%j&bMtnN9~Z9C_cKjUo7WY&>n;zTm$S4V4^2v zUzi9(Z_w(L7tNW6@}dHK5(spf%$aWIQgkN3@Ca6plTSCBAd0@mI-Fc<5wr+^kXc&( zA#(0KdY04G&M5#C02hLDQ3-2)ZCzi0^ey>5^7TLPrfdDm*?tedo6o&2CFZU+KOXt4 zz2pUrVYmw2z8C4g5Zq#Fc52Ds0!`Bi4bNpb-D_ zycrbj1}BTM6I5UsOAr{>q~~JYww-p%^*7k#k3MddXI@~hAL+B6iql~%?Bwk-k_Mrk!b77hHpIN^T~MI3+9aAr3>2{LHiA=UgQ z;m)uC>Bh1W=+>G+-Ba+^=9Uh9(N5ofWfqbbBA~MPcv3i8 zTIqS@gF&d({aXpzvFu`eaM`SDBy%JtF}VoM8wZ;Y5->;yZBT<<9(r#`V`*@vEOOGi zK`t>vnNWNYNIl_v{Sy*N+SI60U?xJPMOR;8A7FyaggDE;5R#S!(a8j9Lo!wHdHFXV zw8BqaNauvJ5y&GpfeI*HRC^CcF|&c_!fO$~RB1{Pam6mD1|bMmQKFNA!&HdqXtIK# zE`&i6=o!y2X4Xs?`F^xFrB4qs*bq#w51&{ICQ9{Z(?FHror{@kM#VUSEL3-rcuYmb z!ORofI}E|cX~8hGbXYE|;Dk&v(muFf6H=<@DWWZA<%<~b(`(OK3yeF&qGp++DRLtS zujC0a9BF}ScBle} zfgP649B+M&^wCvnDvwe6+Cb|x$)BiDMS6_OW-FyE%_P>7eZ#FQl+KNjjTM?~;I)LFY_$^J?k&%%rRU*!uMJfJ# zOqPo3IaoD{?1m+m+U>XB4#-Ae#t>zpN#>49YVpWZw6_Eu>WfBVoM z%_0yM>^|Y`6vO*S0N1hzmW&q7aXP1K>I(>x5RyXfEv?ulf9`sSTd{S+_LIWUsGGNb2{dxa#14@-rF9Ro3cDOWE}U`i@} zEBV4?GI1$N_)hd!F4E+fp(7wA(PXSyuK`Hd{XhpMK+Io+vRD&bU>Ged#I;nbGdqW< zzypWy;T6CXRY8PdV6q8GYmy|V9Rz~d-i>yE0>4E>Yz|Ncs`Zt%*3V){!KWvJ*r{5$W26--lc`J-wC8@;Ne8U$8H}m<>J;jh>k|adU`K%9~ zxbMxiWW_SZLRtW2yy!JySqLT0z=SirTpJi+1Ux!m697g`Q-U4mI1B`2eHCn& zmjVJ$#`HJhBBJ;+@QmS?3quV(VvqB)@kOTgH&a8i4TgvIC=($kW2oaVT8J){G>Iv2 z$2aiOZ<74RSbPk8_xTI<|40AIEGh!1`^uQ0=h1vit2@4F{UPDR8EYg5pDAl2g3yxA zL1k3!QMI7{V_h&GtvSYtfER}0XYu^g$CpwwbByh+-^+88T#w+jwRwny|90xt3|k(S zk9gTw+q<*gK3zS@ez5pbyXuC;wteRoYuvWMF1_f}R$3ado-uj$%-#-s;NXzPiCJI5 zlOmc^fWO=jG3I{iSN_zNR+|0z?!RD8z!(IKVSg~5AqgkOu4f!U&)|BDMQJUWRLm)k zwNT3we?HgjgD&-n)^HtPtiWjq2|iVG&ht}7+p;E|X(bcscF$VRVr`B>C~G}}FuePH z=CQ|bBlrqQl4zpOK{Ue&)Zu_nWYc_~+CDM_g2j6LGD+leA^>tA38`a2HwmYziqR>i z1;WO_JoiP2uxqh^cv*xwt9GDK7Ai!PrE3fLvW!I(k=-4p<5WR^Mkue)Q5wrIW|jak zSJ-2#p0QX>Z7_sbtB?7jB}?oeOutKoYU!sI zrSm|DV$v!?9rKInsnhM9T?cF|!6h{-o-ms@k!0~>HV!SYk3bb^oN+W>`P>APy)Qpc z82dB8iRejb8LBrZF!N8^sw}}7XtIN@IiQ8HIOV-m)MZeM5;!TiMK7lWoRFL|_5_;* z7+}RF0w`fLgtIZBpb|N8Q1#->M=DzM5K(stv`yVtxmtd(7`-+fiiv9`KDy}SPf;&5 zoA3;(aS(B-P7JD**og@#pQ;=^Er)Hvgi%QKqph}^$XX<3x(<>+KR_ea1{;s&yleY5 zD?xZ@g6QpOYO#{CYD#JLp{)`b%UqRbL~Y4s=i3i&|0`1xeF(qh4U4X@ho64dE}+`X zmu`Q^_K@DOXD9OnR6bb#PmGtEpAxR{+a{Tse7k~`=Xo-Qz`(2b5p77%rp*yF_^A2l zc>Q^M|J^sa4ggi;DTFtmu)sx|j>iOUbcNS@;Mo+)2r2bCdDD01fO$GTJ;y(c90z<) z{CM)Y|KFc=brIv^chz+33)gg9;ogn|AV2{Yf-dk=K0HMbr=#w6k#CwtDvpX@r-S3Y z;G3eL(`a*_O^&Oyqm2}F9%^r~iQ{OC#P9o#;OhhKx!}R%iVFLnrUv&x#Eu?1V4uD2 zD!b;2&yx+)s3rJ>0Oaww4_QgR0)k#bs9jj2Qq9UDOO1hOO<{ASU3Pe)L=(L^WB&JQ~ zJq5qWzlQdrV$j3t1`Tm=Y1qw8QJXh+rX8-`XtwiRjt4nO$X4{9GYJhziA|VW2`58n zCJPHmFAkx~%o}AbU3)Q?5CV;9F~;@8P*l3gCeF3&i!Swmnp7pTv#@IOrd!HsNN%SQ zfB{oFtDw)WzF<1Va=Yzdc$EG94$g(Yq+*_l%2d+B0%XyO%^POg*8VsVh%7Xj)Cj6* zdHG4SS!u$MBo?)j@uOmVm`Sak1+DsxGP^-gJvm;_%i`Tav(W38EVhAFd>4$+79>pu z6+khoipO!w6b3_v1)FvxDP8cJ_G%iqxa}a)aTbZZ+jnjcn4R`3M~^ox`Y88}k%yQ< zexsYcoYCXJc6}XzFTr66+D!R5YR{Q>=HDBtInBALF-Q2 zQoDm3E6iiyNj}fHuri;**)eN7NJQV<`DoOswyOuG2_sEC2KgjkvVfqWf_Rsep#^u7 z^VRX*n>;)7KXVR}I)N~yGi^)Z3?z0;SL(K|=w7uf+Wo4Ygt-|Zh=4*p1m){hr5^!8 z#LAn1CN8H5mW&a9ebVbU=! znO(a8%a1qKr#MZt@u^QQ8F>WmRX zb3~=&L8PTJUV_@Z;2i-c34}fu2n9dD=$pe@kBm^P9n7!t?1apThCLj&JHQPrQKQbg zi0e`bi8U^dfaXr=5FW(Bc_Z?+ z25}@@g5xo1xCD)q2LaE+e3aZIiDG5pRFD*{Dh<=-5Q|oUF`_j>cHyuphr|f@P(kNx zlEE`b{>?@UO>1u=&4FHZ1l;uDFi(T9sRdCQ% z!{|Uy9^F?PtBWuWjW~FrxdudYWZ`j5(NnMft_Kq_ghA>8a%ISb>CScu5IFm{ZL75@ z)m6t~F4^MOHugoOxhdF4M=A=9F~}E{%t4b}qHgXTd>F?3w!ewmhoX zWR6ZyIt{aDIes`ewsN2jy!DbDK(kUF+h5-I4O>t>k^3`l=H;quue5(zwc7f|&!sOK zCD>A_wMr6zQ!7Q`Nl?(U3v~o*up%xifD2RFp@+~<0bcqczDIvB<2ls|1OOcs!sI6f zSU5dQ1(5)*XrD0RK$p@LMquM}>6hWu6L=p$*$?B-|7LRlkDT|vIqbLor03QvxoK$0 zm+#ZH*?~E8=SxppKZ*aou_iR$v9ssfKta9>gK3#G)|J^@X*g(m60>3y0VpM^c1&@O zwRX1J*m31nT{W3`B~Nc}tp|biP&k^B26m{c#h!WQXLj9{U$kvoDQ^dUexAn8KYQ?R z?VNl69+yNXt`LMAa%l&^Em?G;2qhA5$%O#daTTZ-FT$uK%gmu>>#w6ODH^BdS~TbQ z#$yGus=o*@j8>qGt7IVG)iFhkJ|7&6(&sUrjercD8DdgB^+y6SYe=9PK?{!84T7sW z;vWCOA*dryY$uOJd;LNue*QQ=onm+&5xS7R<5%!`6V+vt9?Py(W| z!>yU34xA^l;rX_{Q|E)II>}F`1Q?8~gi!u$1QAyA&{ zuD!uluUZBD!!!v2929|Ly{bck>SKyH#bjc_+;#Ac=WXcCU)VVpTwtwxM%k9<`L5^D zOCnxBi&^H?8E0Cg5}zG8c!Owb3XXA~p^jnEhcU4vU`WqAu@ci&m#zNA`!?aeRURSc zObCLY>M=tcn}SrVoW3ZP&%iy| zQqfvfb}WK+>W2b^gqu3~o$(C9sDr8E`E?m~%b%E>6TisGe;nrU6wI%^y=c{#wPe2Z z=t1DFyE?7savQhowee^Ep4IJtjtfH!RHLwRnw6Y)o(-cRZ-)Wax8RQ>Wg~;RPRBHs zMQ~C9#IUZP{4CNzCo2qEob~x8-uyLtG&U>!hN=% zq;H>lDONnI;DM2Wk0W>ojAD${1Fjqv{0LzA>o}{tQ9p5nX$c}SJu}HJSOn>Lnl~ni zO?o2A59bD2o&PSp7qaT*_h1|&ADMNBue+f59Q>m901qT+X>(lnPyg9J!F5~!NRDOX z9=alIg%lg=w7w25i_mj>-zWpt+;XnXp&LOHxYeTsZT(Ivi2_;D`&g^Mcn0P3M&+bf zeGeyQQMkEwJMVe6uNMJ{sLg8HdX2B3(e5uA><|C-32S`u32WND(XPGWD*M)*f5P=B zERfo73kwIVw;g~W$zErJqV4ykHTFZdR7KR8yBWk)^etmL)6Rh!mFBq=H$8oG> zog*ui{Ly}WEh-S|#N6q34ikJ&-ZbYQ-golvAH!#1?Wyf|2?0%_6YAteHKQkHRXwz1 z#teKGI#@`?@1iywr{A2g^G&~cgc}6V_H4CvD;{PC2&RPvtQ||Vlj!4Orv}9>J_VOX#alB7op?+8iS$? zX$P57PSQK0>y-l=TfbT#g^4PZno62D!7BrH-@SL4ZF?IngL@KIT}&CPega8`8I$Ty zhOjM4YmCBlM0Nr7?jvY37292NPMIZEajVxS;l`PK+E8_e%G~jdwTtJY>jPYee?oF|Jl8z5j(V_qi zFRz#6=A(_)iuyg++lkdVZfoD&K}oAgUWsJZd0(`8+9M4^lu{51&KjR%bBi+U+kf_5 z=0?8ELHolmFSdVL_PBli+QpVJ^IV%nAjCgE4xxsG_3YhhHTCs8SE|*?eiRpE(#G-f_}Y ziDs09V07_xZ-&So3+|x4-anmOf!h;KNtgwlA_^9)vxd>2L|~<=0tD z09)P5?|9;U1~o}#n9q%zH28hMIcI}lcegt9>GNC zX+irYM1;J89BR?wev!KO*auPxVTJ>O;u*)X*~zvh4#2%c#Na(3Bqg-w%p^p4vnQ8F zWpdFEEDlF~0#7Qx_HAoMYry(sIr6Vz*4UXh%fc5REuOUq?V`sT-+IAp%Uf1WK3e61 z3$5&;YwX2dOoW7HtDIJdY78*~ArKR}Ck%mtzzR<%vzf&x=`w7G{{1oQC3kFq+&(q@ z%tf;8MZ$FwN%Uw6=?HNVVh{e1kCP{rUkR9mS%eXowF+(P3H1nqlB&i8!4-m3uzv>~ z-Dk~Q03$`?0C+0lCXkEwIox5!qS)!=y7l&m5dtm2%C8{Mj?97fabgCE^Swyx&S2Rm z(j6jaOw2)>=RP9f^kx-Wb1tTLdGxB=+l0BYXtYI&%B&-;)An>C$k2>8o&38Hj60t+i;^%Q?rjO{ zY`_;MKOE-Asg;wwp>9jK#5RN`SnS+$$m{F2hQ8GSzSJU2I1|#6=Rpu0RGuu*#PE;8 zth7l}Po`uj?of~xQ*yo_nCRu3ju$iI7#M-t>u7$2ufdgc5YSZAEO3+zrv37vYCd!w z)oPRurHv8zyYA=*j4&c;oPlZIf95BjY5#J3D8Wzv;lCP(uBJ_6J8``e_t1VFCq@zE z5^@xpsajFpLJ}MhHqu-Um9 z6N^&?Nm?l7+*k-rW*KQHVX-S+*Kpsf(Od8xoFp3|=^b&rpL9FcjTRPY81-KgidIM% zI37SDB}*8iBbZRM3yG&MZj|)_jc{tW--TNMq3qXU{oqfD4)Uh z(B0p&#v$Wu(uI?3$!!nW*lB3UDPE%93WdDsn|}jf8f*))x=%f@)V4|^R_rQ3`pJ*q zVE?}C0TwIlJj;gCPi3A~pX9Uhqlz*N^eP_;mF_kH+R+OxVq0=c00auY_ZQa#z**zd zb)jzeB#ldz;A6y7r;MmLpBfXVQe#mWZf`{~Ug;$VaQ9Zqs6YJV^`6%uoU4y}Z&Jvw zz$@SHmS4pmeDpR$daUsF-dDP@sqgbBU^Uw-Lmv0sSO-^c!wXLJkm*oB%BGZ%xQ@(= zG;=A*rZYu!kr6dzn2a8=$)m?0v*o&+2nxvc>RXZ9!uD<6v&Z%v-eXPcU$9+uTkM~{ z`FHlkFZ?Bu52iwOg>BhgcTi`w)nL-m1*hW(0h2R$Igyz_1j_W==CDI!f|f?EwzPed`q2~i2&U>sx5?>S!v9cjQKS}<_WL9c z0GzP!xNqm%-0bldXO<|c@-_kjkqA$xPA&MU4xZ5ta~*ypr%jt=b!+Qfe|goytYx>G zcUTLLEbF)0hvqF}@%RPr1D^UO6hG_(IP4uYR;{t{tTSxoAzZehP#|r`Vix)`AsAMU z41Q20t3*H4Y3WO&b^MSacKz^_?Q6$$f<7w6_M8ak;{j_ck5^t4k{CV5}?kQ6Xt_=AUwOSMH`B=u=0Z z=QU2f=L_$rq(h#nM>j+*6kgDiuY06Iws-L+e^plx3|^;h&n%<&Mc(@h^gRBy{M zBdxNk+J5!;({|I1pRtc#eud4NJkDlMooZkDn=gYjpy(I}`%d^Va-fAU}PlWyBk9q8#i3@QJZ`1O*UrESvKg5_uC~Pz&mfdi^lWNhLuD^_z_Vl zqEP5~Old#NcY9;WZ3IO9vQRrjA|Sp7gB1FOTT1pAHu z&Po6GxjU}hG4lI9_75vp%YXdA6P7qW$?aR=Vx-vjvFQ_{bV_46 zYh=vh8o?U*9%})SyIJLJT~(dtm|r(Fy6e8|X_Yx1DL{B{3d)+4g^8)L!<8FQeFu&B zJg~Qf)DAz1>bMGMVbZMd5lw-zQK+3x7GN)uGzdb^lH4Xtr+w?yURvxVG846@Sa`xT z97}^pRi{&$N!c%3iMMs}$MJ78haD)kZ`<$(x%yeRpVNXW*Oa3amTKkFYNz_F8j2l#S>z;6vNJ zFX7U?hl9^D^5Lgj{nD`)ynY~{y|TfR2}Tr(Sej~CnJa)?w2PES2rcd&r%AhVwFRW> zW*$@=i$Gcv8jy8y6f}t#=%|!#wVi&-0?#8Tq2vgh*_j#&s3?q5O{cz{g-ePU5rBD^ zs0=kAmiN`977@qiLcruwaYN%CL#I1#m!kn2?th21fHf?EU zvy-sL4-qbhs>Aqdti&cO!mfD;4ZnDNrG5T0|3bTI51W+v3l`Yz%VAxPonku%jJ1wa zud;d6K6hS_36$7iSbmTC5e%%H%a|uM;++b5u8Jh-s z{Fya%HfhW-=bG=+H~+Q0f5s@Qd->Ty-8ozO;4-TnkLE3`^It#oxRq8+w;0;eootN5 za$w+OsdO{kq&zY>nHChGh8u=@^pu*s`J|!Gl%a|IFh5Wm)6ifHcvS0a#{xOh;^w<@ zYoD<;Y-Anga=dB=tY(eYDX2rd$>CtSFrv^RmHCAxm#Anr<^0LZ(a8>bknQgS=(na! zfbiZd95q7xj#OQJ&$XyK)|kc?oh}NABu^$;*boXS2>nF-8Lu5A8b%3zJ99UR;Os7A~?K z8kAa0^#Zr^=hPu15CupeEw+hRua0NZ%)N+h`S}mXV~2+dw%Z{J2I3tGd5F?f(}Yo?{2NM4Qiqs8JOwywC0~z`cx`R1ZNg|=5Z2_<8#L)ej?4a4#&H!kp(O+HVrb-7EB%-V~(;pjB``i zMOAWd@<41BQNHOojQ>z5D4)0t7Klaj=G#Z--(=y7a6v_UvefhoY#o$kx159v zp2&g2QjqFEV^<(n*Y-`yQ{@7KE5J#R-Z%sp?{PM%THM9qkTQ!n2QnGT!SdUS;dv>p zwXP)79z{ZXrZqusZ1+q~&@1jeQ2d+abz`R4G@CD>|TU@9gjZG|p zW=yh~vuE0uzwmXqC^c5XrZUu452ZB_-`l7za@4gRE6E>D$Tb*HT6`5J%O%dU zEK*+LIZ-9O>#;14n4$XBgbN}VKb2sFdp8tZnL*B!FU+*&}`%cNWBWm#fS!tSCbC0 zhIEI0Jjy>ZwvHjVaq>Ya4M5>ZhABm!9LVbk$_FDV@S=YN|BJ8{tCL-JL3N2O`Tqa2 zr`GPV3;*n|?BQ2i?8So_s~JluCgh+oWNyXyJ8k;u_fTa7uC)F9PhDy2pMTn>OrByJ zHf*qki>|kO?^#B>SX5cSnprm6pg4<(q)iBHo}ulKiQ4VU=1pzZIB`Q!->tP!d1Q(r zkt&eP1%mVjA)tjD8EXvgNdyj#biFuZPY7p#c@klq#o2Jih!}s-q#=Z)+H1omjsOAS zK>Y~5ZA+uJx}nYLw&P4Yv)2XyqCj20Arr4Ei-G9Y*p@YGrPvKpVKa-f@2jr9+;0BL zmtBwLyARp^C+@fWb59{lzTOgq_sKE_Gji1@Hanc3E;^aF+aV2r>E~E%+$bA>{H+Uj za}AIG45GgUS+fE-tDHA?dZ3`WD5S*!_YvMZ`PG?xr(`wBG_v@wVWl69H`E3S92Z6v z^-A$fE1650oNgnnbw$Wft4QHi;dnd_0m6Hmp{$OT`GMGK8U$emrV}m;@)|cvj4W|N zBu|ntxU>*`#N(}2{?PD>_x>`NP=*$@w$x}}| z$3l;7WnwhjHP_B_T3@v@FUMD-?-Gbc7E%_471 zQD6t^X&FUmzUaF>_AZ5VLyLn;{;_b`Gwl8AKm6z>ChriD7iH#2o}rDW!0Sy;ZuTH$ z_bDJpV)B8!4iib-CZ0|vwJ5|2CIHnJeb_2T*5b~o*s*M1+1mmhm+S>OD->@LveK4L zcIg#W)_{_c2*e2T*94T`wr$%if{d=bqQV9Z9>4;auxdicw0GBA?b#RFi1~Bu8Qev+ zq6}0yW|9rVgri~iX6(EgZ1>tH>9m8iqumxQxX$kT-hWw!&^=>Lf4|jj++&x{z1|jI zb0uxXrC9qB8;V@G4MbbQqPv}l2-<P)M9@=50 zYjGjh6)$x$^J)f`!>QP3k3H}(0}8GRti(LXWx+LbZTbC6@wbr2qfY?M~%6jd0}`hLAG@a??%QWz9ehKqc?V-g^7ydgsUEH$ZrA z63YG#MqR4`;B}~azjqOlY}nnP&z(B6iuxm`&$*0N-6e~$&b$Swx1Qdjg+Zi4j71KA zl|_}MC_r$|dn0(%_ZRvYnvtT)5>R<7iG|jB@4alr>M5rdc4>h3+M zu=DG=*8RR0|I4|ni(Pb=oH~=Vad4r93al2rTpmTV<_iI+ygpU`%af0wiJ2ui$B9gOeON!TjRI%9(U z<5xawT`QiVQ6NxiynfMQ`_MaCrr5%{-a}^BI8-joUjlzoD`?=^Fj*GyG0BI&K zHKLzOi4~W_QS=U+FFbLW`BqwGqlb^MEpQGtq3qR;J9llPQVrIK zO`kE#7SEsWHdG6VU-M*5WsmpkKe*%Q}7Q?q+-_fz!{kxqu zH^lSqS?BwVFSiyI+M$KmmFK$WykDh9HCQ7SgVPSEI34xAtXuqfhzhz89+zSdCKjG3 z9}Q4Z0p0-bvQ5a0I-_WDIgbpgTT3O4(*%IuUo5kO5L8}4tJBpX3@3K1czQ}4G-pK7 zaq#eKc>yb&O3+5w2VE9qeib0>jB1X1`$3&ZgPsGzec4?xiKmX#Bb^t0Zl_Kf^2Ec=( zZFbh=k$8{7tI46XjUGFWn1f~wD7@4Y9w|)y2MAzWid(O8U>t`!tH6o#p)DJ%z6#dU z^S?o{sLc(9x%21R_wTyfVxw!V`m~F2CsuBQ&#t!Tx4y#41MKPR7%a4Iv9JnV02*{j z`wxfE)X#i6R#FrZRW62<&cw)Mv6CjRdt2eb;PA#Epa~~dw&nw;l6g6$D0W^s24yp2 zWAn~ttC%ny_hW<%8a>=Oe%`VZN*?)d30#BfvV>LOKw6@MQEZYv`OUwx^F|N0O6s_O z=@K`dS0a~QL!=Bk&&`*ZHa^k8g!Y1!O02!SL>NwEn_gwGixryZC{IOBp$jvi3{<0# zp<7rOA97mcZ`hBC^zm{E=z_wHNCAgML2l2y zs0Sz*K^iI?Qyf-dN!wwYGkvmEqG7qS8P`x~s}eWK63FP);?t&($+-+w~IJ}AO7TGn=^i_6iZn&U6@>( z|FN6w>W|Jf8+RJYG8J|ZWB(NLmTtLsa;lsxXb6HedBqe^-HJUY^wyg^h;G|)zTCT<6J=tzNl+)LeeOcM941&@r_Q#Z7f4@4OH4J zSmx@>>e2{NwkqrZzBSvB#U`NAmfv%a9UM0dWXSn4WOZ)*c-$jx?6j$IaVb$(DPcUu zWV(V9NtBR8t<3KnvRs8C3NznBY*bxrM?@bPsK10<{b|53)10;<-K*K_rC7Awa~xsKXe?90m6HeK=ziEK9&4$ov49Y zD5~YDZ*l{K3|F6DsBZzCD_?`9Z@$xx#Elj=9h;DaJTD$zfwYuI6%FeovD~~}sAM;= zA80^clwKYM2^L>}I0~710%fr(e8ku1g@tcWQ{4WJYsZOIg_IW(^pnbXXi@oE0F?A% z9SbGBOl7=&q9WBLq~@X&=t9Yn%+>iU6x-PY zh7zcb!(}OK}3SnYuOWZ2t8(*j;zuOS9d}04`EMObd!YP#J0YI?7vcP*gP^ zkqH)p|Ix7ZVC*TVaGNC1spRhic9jp({{jI45!PdlIF!;ClI^FXt~k048TZ3(HUAx!afoTeF%eg6XBqC5zDTf$o6Rz%4SX^#vw{y_by``sK*$a zuD{&)_uAuJd%-Pu_1BM>J^Nd$xq2}Zas*zLiW$YsZ_Hb=I3_PR!l9i~)Jh}IN9>`s zfw>cgB6P^P?8qMZKk{_nv>IGLA6vGu%;wuJAo7SfaCFXLEbLI+}X zcx5#ydK39>iSEt$ea>7Jg?gMafOZBBnRC=44|30H8%jeInMDrdTR~2xQ%G3L4Wl5QgN0P0NU2XWZzRj?6fjT>S2eD|L%bYPoB8EYX(!ax1vKeGF7 zyWN^_EZ&5yP27ax(%1Fd^js&1jZjn}u{0SBvZuw_90MSRT`BbvHYkgBY0r3}>fXe6`N_>| z28~O!MW>9ho^hvqciVeLn=8MxSJpkqskhd6n`tlao%jt9-kX8C-?RS8@|wEDhVTbZ z0SmmQ%xg0W`#E>RLq>hd9Q{t`t+&(d92J+%*+qjC@~}C@jg-;~#2rpj>ZzpN_RGke z9i!Wc_NmrC)j)Q;FF&Jj?2o*>GWsI#>-4KXCWQaFg|)QscwrJ~#umzP_PSv6A5s|# zxeWkE=l|0^Bp~R93MxZ?Ucw~K@|YJiyzV>pHL#Hs*F> z2R7L&>$h1qGQj5u%~XPdLbz-oM#r!wB}1g1f#DAO$ean*y5?zn?4j?`NGfF!nmTO) zos+cfJL;`uR+){SGTp{pk+2`Xw3#wuF@xY<-C$dHe47tvnzES@3!2dHRG|^VKYuK^ zPcH!62SwqYa{G^=qdLYt8~nUs2r$>;XhUkxTJx! zDfZiC-=$!yT{`a?d+L$pw(6&_x3!5APaBr^Re!$NZurRMt~rV(B2CK4Gp5+YNfT}M z>^U}T(y7#)x8)BlMQ-0=58eLXa16d?Hu(Y@chl#ng1Xv3WQ3xUhZJp1X4<}>O zMqCaG$agwTnvzOxy!ey1cSdQP^`^qyJr)&6F>hoQ#+S-yEb4Lov<`aQp29nNsy)8r zF+g~|z4-^9sXyUZdE|ZJ>E7=1&iXGlUdMYydk2?y{d(mK6&D7G|CD1Xa7${>wta)` z{pE6N#TF|EkKTo0ftMkN(lG{lClBRtF%<7S#9$}LBM*CTE9}NZ6{voFkp7f<1}hJ9 zk7c@$JY{3u*CQ^HkGtcytWZq%DWLcC-wk?i_Mdl^6dvh&P~9&1CvK7z-XTon@?qUL zs#VjnaF6%quwhHH^UjuFG%ou@&QpZoi4_yUK-!y7fO+wtaD&!{`~LE_MmwLts_Is51wJZE{V*R&QMIjJhwHI^1@HFk4e-U9zh#9hkCK zyl%vs+1azZmwT~PmbiE6!?tr3s^)iohc-+32lg|vm20m3sNMG9k1TfnJnNoyh1G#H zW9PzRC03ph@61q7Cvq=;>KncdmMA~2?Q#Mj>fEtC3w`Hzm+LoO01t-{1t(XgAOq4Z zQqQKwhp(3%{Qe;j5L{7e%3zYfuTu~S$tIRD7GeHLbF-Pg_|29*R+2BX;mN_&o}=$C zhqc&gKYSST17votqv)(#{{B|`@v_@(-ds$DFekY7S}1+gE$cR{BU<_z97r#*udcm? zF4nvSi7_m4QdEgzhslNSbtsZ5fqGL9)91`}xgC^-C9Oq_4XNm+3Yd;|dh3W3n))WW z;qy}8{K5?DDXTKh3lxQf-2JlNQRCCAL(eJCLwTNkpL9AsUX#kGWydE42=7h9*&7C4 z_jzN@KC`y;3D9v{_c0O(fl(PI<#YYsQHXsL`+{{iP+2@z$ntE+$JCyX0PI>*e& zqGUkLlW89#=@P?M1y9vlDbMI`PLS=fUkk1F8|A-^#nylSYX+v;=bqQI{#Pr51dGSP zM2o_kO_J2B6;6WAcS}O9YbV>_8rF@A0w92+68_}+-LM7E#H$4n+tHBBLfNHZVdhXC zP)$NQuHjUp4Q>(C*wmrLP;7WCITE%cAJvA?KZUtN30kVB42aq3HDO`|-fmAG=(dmj z*{7itJMCL{eBTmh&vj08+ffQi!6MxcRo3Of^NpFHlpX@_cYOUz#d$-%qCBnVyDi)rjE_bq8qNmjug8%xCWayZDg8u*)>CiYS#kFwD3uj>6yulk;5==)eyLkz@YREG&dpx#s#0+V+>9!9M_-5V}FSmDepScua9{W;q1mDmI*=wmbS+ zzE?@w!D}Zh6M`%V)g>)-f+zJj<43+qsb?eQy3*e~dHw1NxH44eWO?NCt?CJt=;<22 zU~v5XARxejd^#~xiKc2e*JB>c{T>keuq1}R+4g-lqBLXk7hY-mUwYggee?&m4*!{J zR<5ucKlU;E?j5(;{SV%c!nDF|!L?z+#po+~nf_Prve9uJ1#QO|kmCg9ItopkfVyXG z)%P11Cp-a#=Q>qQ>5&PjaVS4^9A+~Gr$-aY?Uu{`+)f;L5XqP8xi)0hYg)M45po6wFZv?K-vVcTog1GhN0pUR(GMZy7Dr#STe}r1Vw;uO_$XdZ*s+F<_+%lr-6$%NEXI^TbBfVlRgqEiDBS zLO}bByx!@Zg?d$KAnquH1KoxL^cgMJ^J;OMEih1ba7Q!$*&|0}ZYC6P2g~ z=h;wk@^`ys+iv_`HW8nUoif2!2Mr#~N42ZFq$8=>dTAE|4!*=h| zf42G+&)Ap$=4(_PwuSTO*=={;VGlg`AeWStvWb*Rn9QOG#RgQ;bPKs1knG{WhBB?e zPE_U)IX1MpJONu@UFj8cvyU5M{cD~$Oi2w4^iJ_Kv^KGBI1ZHRy4GLcxvfj3qu0N_FY%xCN*>o=tr$UiQxJHaMZ*n*H&yXb55N9mUj<2G)x47$9+V0OiiU2ku$ch*yF-&T<+cPA&2m3QJKoND7w{ zNf02Dg{Bx~lrn3xse{-#Ln(ET*Fe3ZShawJSu_&7Sg``jN|TlvP-GAM|41rpgIOHvvUdPYwv9-UTjN8le@v?Vxe;~acSo-Lzkmd6A z1%49HyyTztJX*;2uDM&dA?iS7k1kgz9vprj2xxq=!OCG{7m=$0}m!4$mN*wXbfscA_7M^-~P{w-ov3ND$h@Q9~?! zXd4mYSK@PYHtfeP9P37{0d{Ez$n{{FX!Mu_L|PA64WHE2(rGnBZ?9kTTf6S63+-Ef z@l~QhH#qHaVei_Rv*93zY|o}0cIg+tZuhTv)u!L_ueKhZ(100dS^djTQ3+(`G2;OW zHvLmSu(?};?Q7F(%N<>&_qpF)_ULDW>(@X4BqJpxZL*|bB2OzqdboMejtZhGODwz+ zdv?WI8;{m5YQRpkFn#)TyJqe@yXEGufZuq=vF)jYaVzHv{O3=s{NDcR_wGXH_4Z+* zTn|F)SNhFe^uFYc)#E>Z^zn_=_NJaXYBhRObp;Qfgb;9JSUWfU6_WCVue_wKC|Ij- z?X%_l+aUz#n(W$*%J-kMsVh7gk~XCf8EZ#c+L-ba2t}tF6R2IM+q8hd&gH(W&ht{o zmK!yvyn?hW-DXp8*)$wO@s5tH9c)7@6VECw$UVDZ0hbfDXVAVi_TdXowXUY!_UJEu zW+lWdn?7!a-H8L=iivaF;uDeA4B1 zG?pF+QUHOs0s@5{re<@W^U!sc zAP?mfg}MPh?B!nw9-*8!`yQmbpo*d8KMV?+RABML%$gQd`LtKd1q zpJn>z%d7=fWaDEG+O(Q7+rDmvO&T|vP)hm^VwX*yifVeNZC5B+XI26Z&=o(SHo`_P5V_dG``48Xx zhTV7XGF!7|mHSj7J0+i*6NMM?)IME)@blI|ps+7}>naRtI=LXA1-plua~H~RYxyw& z;VZ>{|3g0S`VkB|ik|c|li>392CT-3|e< z4^awhJ#>(566f&bW$G;oPn4e~MwGFcZ*8#z+GJ6bk}h3zJ&0}%c6G$NgLM&+ryy9G zqVB{-R}zJ%JRvdCtu5GPLi0)%(s^wqn#rA&4olO3y-J=pE2n{xD*th5eXWI=opMve~PO*Z3YAhpY8Pq2flpS5N8-fi~Ev!1zuWN+;3Kfd@n``$gv?bW(XcJ~i| zVM~Abgw;%*V2$AtTeo2&iylV4Anc}%FQb_`00-5@P_v!Zy#6KkyjZiI!94H_(uoHF zCoe;r5`^ZgRb@hht0RTc67mzm%R{}z$#2@V*Y>yWv}z2^?}fT!aJcWyNcP7l@R3~< z&V)RpCXZ4rnA)FWiO;8rjKL%aIQ01oXNbP z)QYB^ZS80HXdb|Hu&so!uGwpCE z=o0VGvT4d$BSdDBSa{^2^4$&MEaM|aWRF;=ajV%2KZRoCTk)O}W>-FG;#6Ffh3(bW zkX2lEy?x`?Yi;UZ{0piIX#rOFRJY4jp5}_o zik$l|5T%do;>euvg=gbl)dSQ1l(r=NVvCZPr{|CKN(k*5{o zXLBGFSG$K`K|m=q?5Z+^TfufN1BE!StKRm$xYrJ?g(4%;f&YP8s1{#;qy6^-Kg27_ zKpTC|hpj0!6#GBP{8}u6n!1p){9)qjhG#o0(&YtW$#?VJV%<`<4|IGe1;-N&0&I*F ztwV^)$>10pVZ5t2n>l29S*~-8$wMv8c4+r*H|AZ$4+el@6>6*HBRR1$eKux*?B1S% z5Fos_2d*bitspV^@XKLdAUjv-izxZH&l$IBlsOE@O|g1d>7DY4kQm+{LdfEZii@mK z8f+jsEf6_ea7CfESWYM(Md<@M2hqp7K}IFXPMbLZtx2e@HTxT2Ax5peD24a<1TK`a zE(}lgzLj>-q|>bl-&zycPo(r}I~*yuHridR z?}P2?D7rMy2ogNjanx?S_#E5$(zABU!g;p#`Il|vth4N~ z^*afuT4STm{s7!Yv@UTsmTcK?HMt`;uyv2w#^0K4=5GtKy3H@z)u&Fjhwr|_PQl-y ziySU@W`qj*_>DIqhq;ILqg^M*yilTY6_-d5ah??{FS(4f2=0T_{FO~dcg_bD{GJMS zK{`Ppz>vrj0!R_RA?p~V92Lz%8yjtqNMd%nKiSu)JbBs(y3L>~5&Rr42(an|DS*Hm zhd_)8?!3d}2QrgoLWhyd72(@bb_AO5a%?MYOWzly@}zmGa5wm`lwwB=WGGK3QpXO1 z)MWRTX+2`4(%7V!{AV_U7*WV1LU{sLUtw5?M2X(L-^NuBvf;d_tg?nct`R$ereqSO zl3cpUmOt<#tC%^{#$IrlZN-;pLoQ`SwPz6?C~L!s2e!BFH&%jtZ_cFAwq^74gqo{I zSq9c6$|_T)&%vxAgUhG;Z0@y7X|!}I!+6J-g3)=aZCt&E?<@fU9=39f8QNjDW?GYY zUqR-`=e9`e1woE)ilNU2M{|z_QArs=IqMcer`tx{-c~+ z+2-t5av(ObA>)d` zoP%|VEm9a3;^yV|dMf}_U;|WBm|&^V&JI{Ztt<}M$}uvB4;^aB@-lmQ?PdZZNW)Rc zHERbBH`-%Qt+VrMhgsYHUG}2~?zgKJF0%D|8!T5f(#i4KV_CcIEB|C&1j*denzOBq zNYfHk*4BZH5J#FLOJT)k4%w*_huMSQ{ReBSTg%FYG6^(f45gU`_&B`tzU8p1lJ=jE z{>Co4>Cf%w_uOlj-1sTG_x>f6;(HaE>DAS?^~oO?mU=992}|)8Z$9MYb`CIoezeZ< zrL2)qwb}y&3tu1ToPekFp)t1e&6v!{?H6otFZePyMBNGLajI?>($j_~Nbf8J0)+R@ z!vBPSyW7YzksVtTmSi?jYLQypYNZAec^nodsfaKoZ77B05b$*(^C%K^2Wv4&jJjbn zPPIl5UWUJFOc1KlyKGc-r41QdYjrq)Ub$gE@;BrkZYzxf2r`f)$nmr>!)y>5l&gOI zs734d+Q{k}+tD7gwHMw`U^O?&NgMP^&Vr5DKN)y6ygXG@oO62{=JIfgw;BGo6z8a?XZK$|};- zbcrz`P2(`*$}u%HzLdnxC{TYq6{O<`fdJthM_|7fUnTaPo8OwbvO9w%*`6%5dXz*u z;;=R~$B}16ljSZHk9NNCcpg)PGx1E4u}mV?@_X#FxBNW{GiZ4drM#oN#99(%D8PVJ z%S$n6&sh@cvZ@{9Um+-vQ8kG2)n|WZrKb!g690JCXWl3m1$vzV^67@!eJXoD!>eKL?bT^+D4iz|?~wOb6t znCPsxv(UOceI)M02)NpqPM~>NY@Nw!>MXVtNT>+cUWcD}$VMYJyJErR_Q3b^-IG{RG(Qg&I(ynQTH9r7SG|IX;Bd4*i*X=bOp!d!s3TYnVjq=-as^rIyJZI$ zQlthvu5|1BNzQwQJLAU%oAq||+U0voqgT!q36P!-sT1(1&ST&pa~6fC=;9es_pYD) z&k-$$OqzRHIa)x@tfWn%h{6Eb`EWWu#{l6SA2`2z-*WVVtLvVm;UPtoo(%8ApQTK0 z7qC?KCBxHX$6z)DwdLCr$)rFjin?|lWfie_2r+J*__YkjQ`Xg;BNkkeSancKum=w} zH`{ZYcVfmigjjN2g!c(q3FZrN{8&yuZIXR@_9(mmzy8I3{P0h0?8TSaklCl%vj;nE zU45s;hQ(|kbw|6~2q}cTFp{-WJYDQrgVyCPVucYAT59CduKc5KebMe+a=T5y<=Dzq zFZak-77~$q>3zr-wG9V>b)k7m%>-0W5KOkq;;=_Cyy6}R-C=vEH<5J|moll=x~x_* z!BKxcth`%*vJbK&FGwdc1Pc9(+psc1{$$xab-I3+wy_+HvC*N397z{ZrZdxmV>vOn zy@Arh899+baDufxKzJuuhrOlE)#NNJ(wdkOvgdW8sFDg*j4w))PfP7!-OiOVDyKiU zaO*@oJgxEw$TXTn(S^{uL|YQ9L-lcrqrnK;2%!QZpMq$TSO#s*4DvEX9hYy*W@KVb zL=W#GosJ19VmgMAZ?gN) z#1vva1!^(Gx35{do^L?mCJXXrM;=9sG}F=Lz9ItRc8CnuXSm7dgJGQt7Gz6rpJANO;4eaRf2Br~@(_cR9lad1L?^NHKo0O6guefQ>D?k1c+^CWC%Io72FbI9UigGXEGlyj_& za~abL>4oJpiSr0-Krw4VxB_e4^D1_0t3iyI8NmK)WwI9~ILB@+itk9!8+Erq0d?E( z;ln|2IopNtw~LD4kVL``q1ye#wij$DHgp}URtRreaa9e*+$l>{4YZn3qpY#3#V+{7 z=k3Ceeb%1dve)*+2H3`YsdYrlt(AxgDU9GI;twpdZ;Mrdh&I3Sob6jjyEgF$t5n3D zY~ANxGtaJ?cO{saz?{=h!Lu{6J`mw0^KZ28FT2CxdPnl*JFT+q0N)ExfK3X@FowCr z5va`;8QdXv^bo($*ilKa?Mc1&`(^jL=qVhWoG=ieUqNQ+E$eOV-rekdxKzs&od`vb#q8#J$Y3En-TZ!rD(=Q|4GZ;eB9U!U)74 zC9<~^apNYB8g7I5TYaF#HXhiI4LZ)EMGaDE3KnQnQ;W?RHpIHOtg!KD_%FZv4*T%O zKV=apxMz1aT32H!K{hiWoi5gx49IY_9cb&e#!S?+a0?C-|Lb5@e-w(|BP_T&Tq zOZ*O!|oe0)2?A09d z!W%z+lU;G;LW@qAWfv^E(Ke@xZRWf`g?$;Z&7G}Qeb&Wx@JU#v7`;b8lG)CKZt+5j z2hx|LFwwOzX`%20B2I&J(n5e)qlp84V*ptwj_gh$en4^#nTdO$dn6|^V5~%#W6IXB zk#bW;gEL6S4FUneJ8qzU7ruyDDN$Vrwo6{}G?y3>j(y2QBrA$yMo2EdbX)ndHFA^= zJ5~O*quFTj66?k!APtKzi|nf;-D)#ZU3S6vp%!mH0B&rw-R)i0P$Z9)$Tip$r%H+} z(X!WaTb{FXPn}?Ozj@fsz#Z7PZ@t-eu3Krh-g2u$LL2I~TCBR3oiyxJ78H!zkku*1 zT-GXZ%~jm7(hR2szd(&Bm|gqU&z3J8!$)ePssZd7yl# z9mG#chA8NA>e89VaJ?AKP(?Zb;bt8r=PgJX_sy!&yLQOV)fD`k>=4kH$T2?hc-xUu zmPFthCK@SH-1SC`2PJvh(Y$ev3!GMO-@7L}B;Wq;4-nql594?J8yqrolMk%sNIjbD z`vC-DIIfIj5rrA-7JH%}IRBBwCDz`C;VtF`o=gr?09ZUD;@H-89kFCd!d}|B#Tw!G zWQzt{5(+W{k}P6J+`4_8P3YQZyPjBQ=hjZJfB)t;ZTE)lR({I+tmf=X?f>2LsMR$V zS^0%ioZ?7Ynvt-I5+JK$*p~q`9uhhI5|a$y|{I^?SXwcvI-5hrrj(H#Y}X{ccks?Nu%xZ5##Wf z(qdo!tD9~2#+{b@$PG5-vMcTTuXftTfs?Ib&P?k>d$ZHAerQ}WW+5~#BQ40@x-s~M zf;5y!5aikDX_Kvl$mnZcehDuwxHe;PiN)|%&(3@Pb=TVi4?I9KX)lo&&>?s3JTutp z<7;~!`d`z-DSL4) zT&5}2W0Io+a+J>IPMaiuHyL95c#QD?(FrQYGX)6mctZPK_^vRUlQpvPHHPzm#$WO(=6~ zMJ6c2hH7Hd#c}l9-Gt&wce{;_b=tnxeQ0?%q6ymOJe>UTHJ91lm@RBrzsVkc61OckaKBgU~Xvl=@>cB1N>y{69j10yQ9ah5rf=Rw^T zk_^)EgFt}rjvuVwu{S9Sfs#V%9GyJ23cFAjxj^M8BczwWr3o^#tOB<}?S%75*pW15)2nY)Vf|N7qu5gL1go0bUqRvJZCv4MGPua9t6YS?d z`=t$^eirgRP!0BdgOQ4DLj||7h4H;x(hmWz{hZ=0f>N=1@ z5eC}`;xSQ3fPA7Lo>qKU&KNnu(i>LW*|lTsa+Vl^fW6ME$Vq!tLVf|`-I%F34yw&Cx;%36~H@k|1>1pyT)DYa%~SY@G38-l~- z+Ck+uZqztCga?#IUs!L4Lj+_6DMk`RCdZ?RG$%{YY%K0poT#|&C1YyD=Org*sosqPZWI)tmWQB3;nbvLG zVAY_V)vMMx2!>&s%Jy5{>8Hy7C5G;+R)N53&#_sHKW#01Pcx3AM^FEV{ZCzsO=#}+Pk~O$(th5(v(4l{&=mU{M>zA z1nDG&fcTX9(?IbDg0@FW9Q`aWYK_EbQZyRXe9Tn#a)SW0jB_G*2 zdfUv*zL+0OaWU)s*>Y?r=$8`gr|3f)uG99i3HV_MO(25mSJ%MB#7bo zs1alAu??GTXFHxw@V-(;G=h*^d%?<#cDC5WQG@N2swS&RC+(iwzhgT$?6g52xZ2LW zdY(P8v(28WgHl`cCl)Fhh%H_>nwmJ2*85u9oqG2`%+ecL(7f!x;>{r>qed_W* zwZH%B7woHFyTu_peM7g9ElJv!OQ7zQ=d?}1MpgEs`4tUmx{RF z$4eEv%tL6PHr^u^sblx{L3vqUSm$9utz<_fEoN>RJ1Rf8JeeR+*bDW3vNlQDCG{CE zJ)^`M*6x;uVvvq61OkM2eBu3$yv?WZ^l~AFjISw%U$72jaQS2z6b~o@1MVocXQJAK zG~%!uab{v|5_Q4CJk)T&Mh%;2qbmoX-59cl=2i$M5C%4P2lgJc^sDQvWI)vJU%JfJ zZGhs6Q*P?%_G}j{Qz8o_rhL%aaX#J1Um0w~a7P0UpG8TDQVdx!CI<3Z8B$0gSd1a^ zrcRy!LXFs(HEV6-#*J1xb&_pZw;sF|w$o>yYB`)nZ`-ojQ}5OalEnEmp@w3m1JD-D zff%U|R;CQk9Z4zHrP!0OImH;#C6{wb7(O)vD+MIy41_3~(JHS=Cu(QN7)y(a!uWdl$WbUUrfl_& z{SNuXFvjlglG?u!khRM;9cZw_o6yK)!4JziJx>Jk$||%ii>;`9fQ=qC)=K3dI+nIS zo_4CO*s$K}Qv>bkZUVjHt}EAx?OH4e5<=gx^RSI6hnj5OZwZt~)~{V@jVPsBd8C^)?uj zi6Y+Dl0AfJL9taLd+Y|e8jh!B951Aw2jPL!9Ce5Fg9C|UN6ChYqymB65M`sqR@dJ1T!G|V96J;`EJPH55V9*m=7=R|#FukNmVPI=ib_#~ z=-uaBY;(^4pp}fCWCJEnv9&uJY~!|FI88~pmShQa62YikaxWZg*~;zP?2=Qa*q#+n z*{Ku9+5`9AXC)xET{#>QP+VmNY&A6^^3o^wjdwlC*n?LVb zvxgqD(mAuOAvMU>Y}(;ivkpSUz%!zozx<__cpO;B-58YRZn1B1JBIxO^>@>R0#Yjg zRRo-1=`IU-ieKlID&%utN&VE53T1n)gOigF0zKoU&!;P|Fn4=%3*#mjGrb^r2hIY7 z_YMHvf2GELL6q$#h_2;a)+J4to>f?f3vvTu{|bqe

|9tfeHu$XbZ2xn=hO%pe4ntvuXyy@+EjSSTZp{8LRR762W{<}d#rMO?+51r1RMm8HBgR~7l7-yLLfkR#}(X1 zy^Iy!;WteLlq-bR@?t-_MW2OO`5Z(AioK>YkM1B-*nvEK19v7$)9n-6wr!ge+qP}n zPA0Z(+xEnECYo?!{6P$uRjm>pzU2pVpi z&{=Pv>#a`};up;~Lzm9_pTL)s>koHzjYLW0YqiJqu7pD{Df?KWJ^~*TTYxsB9LmPx z2pt9dDQy}F#^3}`+>>C@4Dfede(T6+^YtH3w9cqD$>z-Ea?tBhG(6u{FaC;6wd#R8 z$y0}^m~_LAsQFg-4x`mW!`2`tG!*%!+MIe}vLw_jWK1)`YvAx?L+B7(3SqnEe^3ex znZ1MviMZ2M@D|#QyI^dXO2d#BeyV1dY86MVbnUj@H$qL~siQ&toML7=WTRg@zJWRd zC`J)81ToiN+BGwMam!+?+>nYlcWvGe=rCz-2{ySEC8Mko+~(TBm%>*t6~z;`Sxx+^ z*DQ;vU&|%N(M)cc-L8*M+b{N9!D4q?S$}+f{q=agm{s%s+nO#XOcgpbU9hMLrp-v$ zj!YpD!tX(1prdK6dT!6P@(d~y4w!hD zqWUit-DO1IU4QpR@0K-mNQ909Cnpkgr|@kTd4Hue^T1KErY<+@mJJ;b`WW?Oo#M&S zk9qw~I~lNr8|ZV=D;$IR2A<09W^%di;`GZH%_*o&Vu-I zesuBIut8~Dy0KKcy0vK*inSLMnwl!hvX8r8ZAyUP8;y>f&zsqG1~>N2ZT~lWGlFb$ z-FZ$4a4Tf*b{}zw>bZ2++Z~hEc`f%I1GOh!$P9K)5LZ@;0$_%|Q=zwgKIzMQuCn!& zhx2FljsB;o1}@7p6<}-^ZM=zCYHNfnhEz;S#FVmfI= zJIw)}*XWZ8LwpZATEO!Lj*uK65CHsF2=e>uFy564l5-*d{VK`qfet=jGcL?YN7mKw z?6qSdx;x!7rmeAHt_1wx5i@q20v}d0ToI<7^d=+B5lW=-7Tm}xI#uIJD)|&FuAQl< zp|$8w5_s3Out*_mXBevwQMF9VmJAVmf=oFL#Z|wzaC@Iv404mhZ%Q)kA6giCl#4gnFvb_k?N(<P`>LVA$3O5yV8cT#54qeZlGnC6?k>lkXd61e zXL9WfRtd>-L9!AH746peM`JLwcBK+`fmnW4rpt(&Em~6akvR!@!r-ia*7RLTDX*G_y{i7RZc235N%*IJEgQ zJfINl3EPK5mm=PDJI4;&&(eC2kBGoeg?4B6Ud>|bZ&Z#Kp+bBz)PpHeg7Rp|G+v22 zk_uYjs+63BEQ>9g5~ahEOmd-uh-DO~_o%(E=em zv#~L;H=11ofz??I@!}yW3`jC^1QLaTC2cylIsL8uV`bzmCl+Ydv^e3E5UPgq;1+n{ zJhW2X_8Lc!Fra?|;vZIg;Cn^HO_0}dlmkN~NRgE&BQGfq+bCqYr3?%d@xf_`JP%jd zanYD4vJ)1I8E9s<)_P$#SPM^vYH25Nq%RS#!1=SUdmb6@K}}Q7$W|6^1@-NWjJb%tom&sIR?kh`n|1I>Q2#u3G>e1~nFQ%J9ui z@6w^mdH=}m7ahlDu!22!7wQu&q4YXUfX6chwcAy9mF)}2li`>6o1%)RN z&{IvLW@Kq?h>9ZLtnza>Z__WPN*oTyM%5T{sHrV7f>U;US&-otk1Dq!JsY}w18%dP z#|kCvXCsMrgX(6(%I{OR%|_EI-|NhC8&}`(ONNSu;Cj9yI>MDOdYZ`++D?cn!9#P) zLu1R|n_L)r%|Kf}9yF_<-Pdc=2-@WRA7&Yi*KAvVmo={&+Qv7R^TZSHriN;11G;Xb zs_KGnMIymK-_KshteK{ZrW-TW3Gi>YLV!@;ppB>lIs?|W*b z5L>A&w_TUtLd2ltjo?~JcUk#D=Aj1Gi!Nq?5$dBAq-Z*E$Az#R#ZNM#@_J-ZDF9W^ z-zBZLGmLKqD>TG|FJk7U%B4BSP~AOe+i_KiQ0{G1wh8J)*RJkZ%JvcKZ`0W@Vit>S z6km^7N-X!6(&o+ckG*=<1qsY_&u0F`=hYCNv--4pwDDENexnzwA;1VF^g;o{_7kI) zy=UVq#q6Q}k$y1Z8wPAGFeE6V$4|j;8uHggypeIrjCRIqJ0(F?H!4~R$8-Gw9gpYN z!rD~m_iv+cAy*`Jvyplz4uQuAU57`Tx936YO9`U@zAneu9w$P3x{}};lu2o5d`02Q zL+<(HkP!|<6NUN4U9+F%jSf@ae<52mr)p&%|0MEUn=${I;XI(NLP*=Novm)N`9&K~ z@8+)%qDjPK;uIq9FfL8aSbz(@Q!ihFhIOI`X`&3;=#7?oxS`T!s|7|Jrdsi>$d?JL z2Su1n<2wpz)n!DNC0kU8l4qOFpJE7qq^w12s_2#G*;ffJl(dv>_U3eXNPO~oFMFu` zoMyo_URqyHAbKo`$GcG7R!3d{QGFuU2d~5>fO4wT@DhS1L=@aR4EmP4cJ@D0p)%V2 zL--z+K1t9J1()6OUD8LS#gPX9rl?oqQk8VOI~L2&mEE@}Ut{$2R`n&)z4l4;of}r< zIkwxj5H(n-`tT;nQs_LFBdE{$F>{og{qXMj z*dD8`XDacDsYjlqbks>cQq&OAUn0u)ggGYa>e?-O{(f&F-@GgIPG?4>=Kf6620!RP z-_Vlv>7@_qm>d?m9q3jT-gi~mjGhh=?6GcQpq^w-S7d7xbk;< zl2Hx#ttY*{uUVRO2(|I9f|(!?jk48P(Lz`o-nF9I4O!}n%jv_bTSvWCp)ei=_g}cw z{rCqi76{f8%LLm2aJo)gwDDS4NOn^B&ruphH>Ob5jnQ*_S_Q^X-KEWK>ley$Z3uZh zqgU;3a#J}?@%cw=Y73FHbU~%2+DWPbn0MnniFmQ>&hLoUS`DK!>8z8j)gCjc4BFt} zRgHJO_p;W*M0bf8ty*>$r|f4mCnRq}_z0DBp%(~K9KaZRF<5@qtlNeogtMbIO{N?0 z0m)h;N1z$ymq>4is$Z+AbUnXHWolf_KnCd)H4?EV@GC6$A7C!ycNQWOtHn=4Hc7+ByOj|<(GU&#-dDFUCRKw}btwOm@avvw3TT%E zq5e~ey>b50@xTB?z2n6~BKBTpnoII^NVCqR zkn-6UY!AW^nt>*$t0-yQFQ!{p%*q?%+1i@5JA0QmT5Fm#lf*VZp0>>DYBhyqxo{ZI zQF&B!jNg=g;4Vx`A0VepVK!VR=5Iijf-;#nFs;RKC967}lH&j!txbF5T&thP!vRFiydeAElvx(gn;-YnQYahdqs+c{CDuoBdknrfzmw{bJCRHv)_lLyvT!#3O z!CiEenYaJxa3c%O`v)aE=ZKuANP33fYp8#(X8onh7N5tg6QK7Z;H`vx;EWyQ2aQ^D zyA8}BOhyV{bL9*0WO(gx&*+c5T*jRF6(M2zNT!;C@T;e|4q~TIRfw zu@*&FM+hxb(PA0i2%&XA=5v|Gq#@8W4NmfWLsi*NU9O@7KXM_|wCxlA_=1e0e!WIi zQNypn0waTN!E1ym{n=vb|G`y-$+1xSE8Rw3;5y)vl)A%qNYR-98A=)qqt+biwx3s` z%5F#vN8pb28UwNl5dIVSW-rckDrXE8k{3aJU_l0v$k4#6k4z}l$Zu3wHx*GhJaltO z^XG0V{fW#*-B^_Z+8=p+t^7+DIGr~lhNFb{S_h1}H)k2_8&_!vj(^a@=}6?DM8ZoK zL0`!xzG8J3wUIaZo&kZ|JcWkrNi?<5b&dm%|>0F-ZzLGj` zg2||%lE}@3!EQL8T(tHy;3sl3!)6Vz$YPX}RL1fq!7M+F+L3>HP2wub21EXMx()$M zZEnoL2_vfh_Qo$l+rxMT>s{aHG`E2Ve=B*~zHq4~w-GphqrB%iva6TsH$R|?&D*Tp zCOGW`DDGIffMWop;P=F2KLR{qR#$VrE5PKP9s-mxbeJDP#ZjHCUT)_Y4-Mh4pT>>G zY)@+`A;rJ61|C$ySMKWY<%^Owg0?g9!Q%2VFRp>p>ZaHL)OL_IGhq-c?u|0ozFr95 zB$X^K3sF=LQ&c4!m&ko6E}6*F9c2W0O`gJbe7u3(We`)l$+nB{Ve4)shR9Q#V@bVo z>%hZkb)~auM(gi;D_a?khkf|3ES}kwIz7W+qO45znr1WspML(Yr`=Wx_p65Ah6gpd z>dk3tgY2aA_^c`s>{lcB3{lF7j3-z`*ocYsPUv@myiS9Z7lV+w(r&hXBcF#GQ#oDr zA9cJ(l=8&CxUx|aY6$hSK#UnQ9CGNoaBOFJ_2g%|rZ<#Q+)M=NRu$3-on97woZO>B z%d+h{*k*b5xWUO1#=2UAM8K%YfVQa`;|tiKWVzy>9z((pU!Q)=stSl4Tiu^2EPs~x z`^bj*lW>9~LK0rX)syM2who{}U|>Rdt@>yvCK9cj1|Dls#Z8pKe~@91c6HoIvkb@532O5bde zTz+(>JI8_Nhb_YV@X!P@rG$kVC8uIK5|P1S==Qs5q->gmm=5S|HZiV5R}-doANrxc zhxzI8?je@)g|_~?^ZBjg%-8NthTyuYuDMrV2YCf6AyEjE0Tyd2Y5(YtAY0tA(STos zq@<+%%872Bi#d8T&Dk#GzvaAYV7E`#dep|^A{)R#F@v`4+>sAB2SyDSG^n9~%nx7mg!6MZj~AppP$%G*H@Iz5LL z3~|0+;TDwN70CiIIhRQ9twf*QtIxBgN(BBB>QaHq*w zl5HX=g7B!-g>E+3)O}zvU|~lA z;OsNh-$drL_At%gt*Ua98*~GY8z$o6uZB;s%s-GDBxYkA9|c* z)&)aiX}7+6W%=%hvcr`<=*nM=?1ey`W;vcX$enDRDefgU(X*D|1ibs*|d7Y{Cc#Z*D(kokN(o)wS z+IOLl+|sg7{`@za65)639Z@<&f#?ZiSKy3T^gyDz3@yVT$3EBJnY1YSQeyyPT2&2k zZ$ZJb_^(>0k|*}$gFs1nu7^NG{rhErID(8q&9AvEBPIMDWGJ7z68aEXd)h zn?3G3F~97EXj}Up=J-{=sOGcc6fI9tL9>8sP`#Gc7^dF5j0gjgJDdx3w^HA(r)uhZ3cQVFgTrbB509zANOp z{spS_ZoK{L+r0~{S3C(}08Y|!*vDrsKv7_wCW`o#>$!bfB&UOW(%6+gz6a#g1eV&Q z%X+dA2Q$hZU=f1a0ioQe(SLY{-?&rO0++D)7)d2bv+MlI9^fWI%4J{ht2Yxf1%cmk zxBHI2sg1rBn;yc`NH(Yj-Xl>Z3p355z)q>aFuYYj#E!seS<;>IJyisfa5j@;HHze0 zW?uaqIG)b2#d&)p8zOsy`zFIC6*aofT?i+iwi?mwia%CT&;otj2WgHDX!0jbD^?WL zz~J)QF`u)6eUIU-ekaHCw)x3e%rx(mLF=CqRMt@Mh(U{dM>jHb_U`}+K^zD^^ExLy z1);N~1NZvhE-bNbY8OyiIZr`BEneYx7o5M~jjja1_hOA=n8kb~PQT7th~$fcxgZaK zz$Fw$gcsFnHSFZy|GcdPH@y@)&2xuYu?GX;yeN9_@A>&`#E-}Ca6^&%UR66+zh0Yl zK~|09ZL+V~e(zX5thSk)rE6IfaA~py+Y?jtl>4|hnt`Hl$ZH@Gk*qiqOsJ}Ybmb>^ z01-j+W`1rm97u$&%5H&5{=B2hYa?6Lvz@Zn5W1m#HkK@`HC>FucM_VIk_Mv<51VKNk>FrWDGle8hL>(ZNZuHryV9&7!GhG z?@GLEfc%#U+%DtckWh zQYa5(V)Wyh?H7Ss)#3$mUgGYH@byESqM}$(_iit@C2p&)Yf&YSkxLqrJhs#$F#}k`zmGLM}5Ku_x55k6!6h0jrZ7o>lsf z`?~cwJe~^$kY&p;SZ{RWq{8>tYulk>((DS=Fk7?B0A1I4&&M)?9#GYDF1JOvsmnUQ z^E+C8b9own+)tl4HI2pg>#-#odkr&nosK0ip`1auJ^fV<`v%+X&dAQ}UqaiKA>5l= zUlP&qT8;cDQ$IN4{*uJvsg-7Lc61_3PXmv#6%~csYK;H+O)MRds`*&qxx6hZqDw_w zb+%A-7Dv4!#Abyg{a?Ol%KE9`J(TjGCgM5jg>3+!Tpfswu*K%dtTx<|oY=|Y5AlmE= zhAZ*bZV8PgiK{kxDPC=NYfsWaERm{Y@?eTm+Wa3mZ0chk4)*lCkrkAXmnO1--1uE1 zrjHk^#WqPo^?(^rtWiLc5`p#uZ-T}npNOtZk#KL@Xz zG`%?bJ#FM5poKl2IPV=l@dTk4!gnp4{F+7R54o0_Lxtev-Mc3s6;@G6)l!hRv-~>l ztGjshkV%gi?4Qu%0F!g|3%?DqcRqDZKz=^dY%(N4!~r4;VDX z5T11^PY6Z!5F=QV%9%(XlX{@AF2ls%n8Q<3dZZVnr-Y zcU{Mp-8LW~{-kzGvxWD2l zoMs>(AFU1(;g?Te2Yn?#pN_7iDu&3q&gHb$68cUo?RKY1+WuqP0jPqKrD2`~os*Al zzYG|*`+4II2)wdf>%U}+@iKi+$1VbMc&2j&gUCKh5`UQ`1mO(7s7wTzy!%{xml}zS z6dJ;EP4avi&LtN4%FdgG1X~p&2hz`7Qbb1 zZ1)0Wz3_8VR23hHR^nSBSl~-G5~NT^8LnzW%2HT6r~-~+2uk~K!><<6pVo_%v0E!- z+8N&8OaRKtQG@}CSI`T7>Z&!NsH7H?4T+hF)P%|?O?+_k~( z#F}Sk3?OwK5)%hvv?5qh{)bcfwWBoMeS@-bdhzRZp8jkIM|Ar_xn-|ni=1ZI`z{4ydXG*W;c7zE-55=22O(l*a0Rt*cHd)hro%mKpPA_NllD$M7EbY&FS zyRmM2XR>pFxlGFY;9Hz=@OlPGo4j4qGlzXAsI>-A;pxV8m_OIQMn)~eRZ z3T6eE@!lD3Q739cd8MEcpss=t<&cURrpz3&7L#iA&8zndK&a|9Q0F{3rW~g~S=A9B z?{HYwc53{0`}irLa+UziCdV3ldS7Hq*VYp$9mTlHuy>DM08YIovqhIdbpXM_9;#Eu zD~sDdBI=L<>0}9KcoMuOgzewvsb2qWctN=~8HmK6GFOflcF5W+Fcu~WrME|&%e`NH ziosVHCr^yVt}i_W{HXoZqI0(bT_bKc>Ys~83`5R1o({LYmZOKSpngq;9#u`Mk2a1+t95suj7CYWOf%jCT-09w`-e;R5t@ zGWbwQHDb{KanwNh8+R#S^(kBfaO#Qb*bU2RZ_OfzGE_))3BU=!b!ou%%>6KDEVfqJ z^O0z!qO>>9)lB#58IDyG=`kcJv<3@<~}U}qX9YPO}}4D zTJ0XVU!$%D0(Gj&3!H7B4VLvz;sNS-f+|Mq*`)kLMO6|l7#%tWeo6T$0ELy>+LB^= z-bFD@tbDx2qS;F=9dx2tGunT$lmPrCKzSVolDlR?3FI&uNK<3q)ta*%ffQX7u4nY2 zlypiJAZG=MbXKmWk4EmG6BHa3=|znn2@kb*`YtKT^=B)8=!NsHzhM7uM-vOQ5`cP4 z5Q9^khdZx?ZD$)nEf<(XraG{8wA6E&0C9QICg0Wz=3MP`%$mh^3OnVVe1W(QZt~J@ zzsoNu5h+{6&gl}*%2SR@hK9slJ)oJ7F`96Auj7Yp2N!|{qR{B@#ciNgl*@(;hapLf0hRy>pk7dbPH$dm%M*ZrYO?zH(B_?-pfh2=rer85 zGsRvELFW=Y6`O&nYk%cVhzG3}k+?~CMxL-FAwfyQo(TDN4ly22LMezUb9GRN8ls*oXS6LXxh0 zpX8u+Xprs}z$E=ZiGL}xYxq-{gOsi0DnZl$`tYX7-}la0VFZQv){<2GW^v(-;qC*W8=yZ{qZZBxl{CG)qm}9c$KYg6HE+N*{3< zph_;&PJg!<<{l3uUXg|zIh~#Iw5f^RM){G~x<}yC{2bV0=k|Wx%-^2|r2+`%F54-x zgp{)4t^rKK8Eyul?LNt0j;-2yam6o-$3M>Ya?AlNr5H7R>U(ZaRb2;sKv^KLk@Y^7 zWL`1t#v>p}o{UZrLGH49@h2ENrK<^E{!B805Wz;%=>OFMt$zT#Q?=2KSvptM1E4fo zD&Pl_-H?!$yp)zwW?;;FYNAnZn}@C%^~$M%3IQ}y_Zs29fJBN?3rf1PX(|%q1;M*L zX0X_tah+^Fe)rM+Kjz8%Ar$@u43LnmppKAgxA5t|6(i-2i=`dm&; z2j9RXsOStQuKPK5%6@y`c!V_=$-?ola0U@{Bz30LFh?*=X8BdBDS2TaYO0%s%P}Ic z;rvM7+;oYp#8#fC!~9#PjSUFBfcVAAz$W79Gfxos(sse!Ot>nLi+lvAhZeP6fl#;uIdO32pkE)GR3ySQ_19rFoE>&0 zYrG(Xr^{XuiW9huI#5Qakrx$twjL8dQFq$Jmuv#x5|kwsDrTq5>sb6aXGzm5;{x6j z>|H{Z+8SAv-!eX*LYuvv&oq2eyK6NRV4qxpTsja#*fzx~Jc9m~WOPjw?QSwq`^5X! z`dcI`E^h$h1*%=C1I)2!qSUd6e*12~c>}1n8goDQKUaZQ;ob8-G{El1gAT{5~c^r_sfb`Qc zZ%#gfatf7B?#<*@q*Sf$f5&X+9@S$z;7QA!Qp1Yj`sxN)AhagVIJIwH2~5~h-phj| zoiS14FBw6DW}1$fD=qoCQlBE7YR4I^;D(bWymvO6PHChL0=UXv7W z$VE$cZj4#VXvF|dV@jMun7vNQW6~vYiZad3W?X+V#!8PUXI3Hp!%p<-xXCFo!!tADfkw*PKf2sGt<7h!$mLx{^ay9;4U6JG z8t)>7#A(T!2Cf)Muk{We)MfJRI2T96hSHK9PC<%K;-qz}m+|>!H$%FO2;s_LHBIhq zPaFw+qm`dlI&+6vUm!%qr2~5w=@=y_?;OTq=(pSE?|Ju(_8$~Wzps6ON1d(z?}T?eV?l z3(hh2TO?ByJrj-EeO;QKE9FovLBBafMK%L$`;1%ru+qO*AGf3% z35Ya=Nfton{Tb@E&+s1C6T#&V9-y!T1f-iWPBt#js>H}>A_ONl8Voz#3mHJgbowre zv9?>=19E9RpQ`gR56A=)luDYA0EvVY=OiGZMGkiY7SOKzeRnU!ijE0=A+>l4;UKZ5 zGJnh|Urm{Vn7`MWq}48>l;PCrN^&;CYh8)QzFE*Tz_-L=E)1d%>&@xC&#Qw1zZoX( z7x4j=AO|3X(zlwl?py6VVbI!BezG5cR(_kq04HPHqHAo|QUT(8**Q(&38GNaVRTEd zEdz&9SatfiCcreLBv5Lb&O-0-d?ujw&FGC-{jWX4LG`V|?0xh-9(f*bkOsn9F-yX{ zHdkuL`1!EjC>nCqy%yUQ5klJTV!_yWlm7XKhkX{bcw3FO_F zy5NU#PHiR*qa*p01p)CBQwQZTfmOl*@hIM243Urn6J$1_O6yFy831WPSy(cyCSKO> z9h&LAcjCEQFn!*ab=p&1P(H;%019D{xTF$b*NjZu&R^pTR4|dqnWR_9$E%#2DEozWkz`(J7} z!2Fy7(ine;;sYH3D-75SCBzG>8LA;fm;h)EB_}0Dd{i@mVWnhYv3)Eni`wf+X<+3^ zyHy>SzxNL0d7DDT>ubfWC9w%gEyRjTO#qRWKb=Ly^*wm^*%I)2W1l+Iw#l7g%;vx( zF|3c;YD<=DQS{%EJU+Kx4(ru!u3Yi}F|AB=Bb%u-au(Ap0*p|sPn$7t_(0{khV*D< zAAQHaY9gqW2XbjJJyD}V03=A(5DjeSBof-y0_uWr(1aL_Pk&PhOA%nT07_{Ko=PP}lBv&YyBlUV|z4aEM)bL*L zdY?rBj`{BRR7uSZGGtRql5YFBssUwaCH^3Givm-M{v^xRv6%uyvFaoLmp7Jw^0wM) zZJ46+Gcmr~!7*OCy|fbTc9N@{!!blAb0GtWmo-%cSu-#m6>XO1T(FQzQVYn0IY&3U zC7~y_HPNQAoH4q%GeOxa_}xMDc42)5&TaSS{J0Si)c`X>{Y=iPxLF93%+s6A zX(HL0H>%BJH<&~|)@BDD~QzZP4Dwo=b=7k{Xi9wY&s(@t&wr#hp?fQ3c?It@mYsh|e!>_4S`nJv08pj1N>tBpvex@#fR}`j* z0roJ%Wf*Fs@u7&hlZe=am%u#K3$pU)&A>Q}Ui7|&#poh!iz9z>YS)LeIpTjstnY@6 zCDk_>)tiJ|#5+foW)5L-j`XS(4;GyaA&@Mu$e)~HdiiZ2wGdWB)SvHM0z9pOoZ5)q zenq1`^HPUp5{kuQ_2uLE&@v!yI6QYv9VUDK{I_#V=rdzV?ItR8dXY}vkc~mZ1-t=uY z+QOCsbx9oA;yLj$dAw~*OvYyj;g82=GmYBb2k8uDj+t@ibfv)J!@pZz2I+-&k`+`X znW~zM_Wa_$#;vi8CTx-e0l6_|XIsX3R-yq-GUW|mzP`Bx_AKV^e3NzItaM&)uTa4& zF!|JAvm$>AssdEcwrK_Up{qsrr{Ql&i0D4eEk1xO>k3>n)~H`M%k{kD$o^}emPG>_ z+0UHly)`O_VWt~QGHhDA+EGw3Ktda(XT~xx8FHX={Ngsn*-digBvjA z!80Fj4YN!cHtxl*8n7VpTDw;LgYkl`lt`3Nr?mj|jS_>dEfq7@f4)K)wv60&8)oo# z247RkX77$-*VF#?jPW~PDhVd)Rlhj<-;TBVJ?w5YWjTuWKMb-!HpF$p+B5!Uit*xP zJRI6+W|A%Za2ntMeuBb1s{-v5yX5}#2ZF=HwJdV$71sSp|B6-gTQ<%QE$=@uY$qAj zV~C9RQtA8q+lEn?-E;v(U{H34>adR@gceFXva(x05(z@xhg7$e+-|%N0Q|OnV(*|5 zZR%n!goTk+NGi)ClkfgruPPzjF5-^$_I^%Ni8vAEM1`yoHMuXgK>P&^XJWCh5|ZjR z${0@z#(MnFK`!l3l*$3TbhuI}Z<5+1=EVf`;4!+f9_Zstt4u+jFi6=G{EJ(Cwvd0C zvI?Na4yO_?x)Y0!E9wh{=opqJ^g1m8Y@!!>DAkk`&2EQS#O5g0=CMxGVB!s9T@)PYeaNxHt%9p>N(_Brv0s=Ok2@_>nC1kx7PS8(d|$f9ek# z=B9#1_!b@oO)yHxN$xE}YF!4bZ^Mvm0Gh-fTD4IL^+9&pvVp%%%`f^btA0auozlUl zUs_1K3XRbNs_#!ycx&|8$h&ZgiUD(=gm=YC36K2`5>0Ag2VMI-d*_`uL!66jJ7W#D zV^=wfn-ee*gF3dRYhjTfAtbLq8wibqKWiK^rkfEF~r7%VZa%sdn0FH5d zQEVOUkbi$(EZI}Y4lK$osKgY{zs(HIS{iGl-UBOmNs>e*u{casmcu*{VaKuSKWjy%ySDIiD{6NbXu+)i^V0y{VdUbkK*)jgB%Vl96(__Ga z!d?{@a$n-=uJ!pIZQJh7A4V<$C)87hsLM9!{lX7Orna>4LKPH&%@dsGrC6f7e`hzn3)q9)lsuL>8EfS+dFO?i}aEr0jpHyq_K{vU;`B0K)LCR5A`!CVUaZTBe`Ry4O1DSC;6uLN}&{Gq*j4g z%K~+gr{vkES7ieltXu>Hwvd1|%H^7gl_tl9s;)dBU9uo+Z%6=Cb&~#)l~&AZ>j>1b z>s~&GYPC8-ZZ|E}%3n(Wpg6LGvgHzfp}69%2u1aMKS}j*jiyohig&Ao9Y{VYcELn7 z3Kr)M#);sdW>D_1MfP8X35Oed`vahHG3QFzGe`L?t(bru8hb9G!_0TZ`?yWicQ&p6 zJ&!1O!1iVw1j2)h+NevbIH--580dayR>Ik%>=!*`*Q?!_I_k{~U1tw*iWn>+);l<; zDUbU@K#EhSgw>nqbr2D$gDLtMeBhBj(7@LyBJ!k~5*2JCFrb z4Hl#{#-4XGLS(jY#Dl3~a*{YG;kP@_I2R$J3;XK<_XAx3Qh-kaK<(%SmgVuNhgQr6 z^_Vq0C(CLISh;Hwl_XUb!&~MRE0;d$v=grF?o)wn466a+>ucxbxL{sWX$hwWc=JjN zh2Zy3f(wZ1Bo*y$OMhL|sM*L6h>PkZ7K|}@-b42JT^1FR4+s7xjos_j{m%-*8A%nu z(<&n~tYEli`>x=l0LxZyUrdZtFoIhlx_yimkl1FF<(kB zd*cDn8xxeFt%%ixB8Ndj2!#t0T{0nh!eXp)^D=t9!`~4)(KY1CMZd!D2ObAPfl{P7 z3L0^a$)Ca&-F6T9vpHy?LV|}{U}16QenlmEKXe(w3B|9-!TW_`pN{0?W{BT9)kSKT z-8CGFKNx!D?6XvwcPUhFkpC4I92%7Z7U>)Qs&GrTQkh*$s6AveYWR=zuuMF57E_(C5|CP%#mbz0vEp+_T z@2~rIyyIOz`gf1sWbA;)b}{Ui1$tAfFVFr!eD)b;Dk=~HLTI=~(* z9j=x*YqE8kj;;H)XIrpSZ`1e?N8&S^szOt3V4!qsZi(EAh(h1{E);t>L|%F zQkt4*XHFBr9VxAQHN)LZTqvbTJ&@2PU3coBM8OJNwF=-o>_lUD$z-hemSDW4JPvmx z50%CmZHR2vfhd-6k@W%g$Tld6r@1zAlVW!y-*Q2D>M45MQD^aZLDTgpm+ED%xdvEW zeQ1jcBi2yUkB70ZR#?RU8Dk`+fwnS6C_$Wgcj$wmWo;EIJfWy%PD&+Xcc4f|47Qi@ ztf6zG+*zBznCMcXGZU@r9PzoyY(mbKbiOd?0U)kfeI9|@g7`ukS#MX;7ro|U z7rp!Nf)PCczpM9}V7B`TQJ*cw*kMl{MS81R4(-NGsyK9w;%HfRX;&K+pZdHHOUm3LC&-gx4^7MFg7nS?U~BkmPIMvH=>{$l2W$N#kV5jLQ3a<{Rd_`k3e|kZ#}k6z=ksCRicswNMxVJ*TN_n)JT+h&iDJSDVAn>Y&Ej9 zH(y_Uim#v44*m~fNYE0jJe?6#t!DL0T=hVnNu(r{#u76DxaWdnaxozc$`_x++X;h*Gl0g-O^@@z)>=Mwmlh zF?v^kevwlPnSWwdLVBp`1H)EwpD5wL5xKZrA5}K}=pRa}N)!I26rPt9OKIWihde|z z8Myxbc#S26ASw%w30_yPG3xG$YlIPF97r8=g9d9We4DCLoLwT6Z3x>16iw#DY`;d zA+umFmUdN?2RYrzItR;}QzsgVl5hde@yhTyEf+ZtFm7TNj+qL3Xta$bpj8CJ6`lv> zY)7flx?ea%4NOS8uMF2o%W-{)edL|6nmX+FmNEB>;c;E@25PLll%n*TF*RQsCHN$n zO4`jmlpHnJfy$|g%*IcoDIrJ8DRw&IGmkml`uriB)1n5!XR9ywZcFBi2v;FTu&Fh? z`Ja6E?RrD@>;8W|oo7@NTNj2yq$ngHO$F(pW26RYLXa8)hzS7+#n251NE4(ZMT)f0 zr3;}1X_q1;V5Epj?+A!UktPDtq{#iaSMPVuTIb)ab!M;GduHDKJ~IlNi~St==MoyB zZWo-#q;1m-G7elNJkyNBkS6wWgiWBShdj1yk{UJP1&ee!s8wq~roF6wW%u;r0JSFA z96Z>xnI&ue_Nn^>`~A$JPfQhxYw#spiJouMb?U|WXJB*X*H&!A)9}QOU_Zf7P*%@E-$Okr$Drh7N7)#BfZ`xu05^r=( zo3OS}w@4%hgszorCks@M+1}40w_mY;wKwTHn$d*NB@F7lsa+z^YD$t4ojH^qA?aT7 zUKR&Y_D?`^+YfYU$BssYGmTlJO`LdLJ0$J_BrQ&tZk>I)zf9Y6rK(&2_E*vS{}SpE zJuaO0O0KzWF-w}P0Tts*wrD-+t2!69R8m$wm@9QvR+e^ z^8DZZC}rFv?-@l4&Yo=y=p#nxrE5t1Jp45@2C!z*}_XtIsHkX8ntm zYM=)$T@SsE7N)TWnev9_N8*4V%HFDDB+oiCVlCfH(06_g$6;}>e6Y@MRQBy+ca#ySM z`PJM0?=@JxFAuJAK6=-;9V6ISE$xE1#Ao;D-$U1zQjtg$xZQ1kmv*Y)FLnDaFq5F)N1 z;cnw;nZZM!L5rWY1y+JzLS$`fzJ^0R)7f}KZjj%xy<-Fz>C!vdRBn>Asd#2ugb|7S zMBpA8CWO)QBPfR>36;yq0!D*K29R}b+h*4OE>kc(7=-3xUX{!#RVB19PKQ7mQ>iq4 z=HtEHq87`yyjiRb%tp_^fa!HkV|=C7pdv?-qRnAr!oJ zRfCP9XDtQ(nl0oJrR*)?5!3EZ#qu~&g6WFuOf|DBQjYbR1)EIIM-s^3zDSl%A6n>{ zNpjnBoo*MK&jh9OhcA`CV<5~rC??33VcA2FqkB%YSsLHSto%l{)Hj(2R*{mafnFk} zxnWOC;L5otTt-3Ob`ZXovVU*i0qLzOQ*~1dv0N(v`#TiOrb`Cr>FKD0GsJ1aavVbV z0hkfR`O?Tm+Pi3nL_48+c7(NYDyyQWQy@Y2s%{dvYo>EWlWnI0kDZSzuH;r0s3uX{gP6sU{zP-i}yM1 z>zal?aQ9!te$UcPZ{2L^?f;vSYO?;^p^!_^gY9elw-0uFs}dqPsiual9^rkn?p^J~r(Dt~-8=rCXgxP2G*(q>Y8%cz@Ldb9ZqaKYnN zm<69w?0<#p&xvTq>~*a%m~*vS4Iw-1%>*qXX;l{^Q%j+&)zS!jpY88V}I<9s`B>1O%~KDi~Xclq0p(i zB})}?%r6k_=Qq#mT&*PV2tgazZ#EehD{au#vB(`m<%VL0S^Oe5-8B;U5O{8A2txTh z_4ac4&&QBo=e@Y$`cRmRlXX9@cbnLDf1IzNyORf^F+0^yRwVWmNGd5%JIi~M=Hjha z49bjsSZ7q;{`^3}J%4X#hOpG<;ctFf!WVJAW>`hKyj zqM3>VRk2~tX6n;#O`+WTpI^63eH*Oh40QmTkKRac0Gki`Btct(BEnX9gT7qy4W zfV`Qh4l6xzCum|UJi=;}-Fz@*)q()@hrdUhSLQx<&o+p6Psfj3t3YB(tsO$E>BnCV zR)led(3=(0TIp6>YFzikYCGi$ zJE95MM>m+x^Cs;+;!~_(rOt0F1fJcJ~EQAqQ~&tn9!pe?`*KHS>ntuTgvP-?WwZ*_m?vF>oDqWYHr{ z5hv~|rC#$B@)pVuY<0~HxP~w+E@jAAvGp`__2<$4`N1vgbF}i{Ni4;P226T=Z}b%) z=yTm+X9wB!qfE;IrP{t2n9glyQTpzi+8kA1hoS&`8Fn0#9-XorwkBa2(xF+tzxSC- ztJbSg6R7DiefY`$L8F3neo9gArMV$(TwMKHfl^TH3H;rys}n&o`bL`#(CMe+?+fOx zKe5zX^^N;YsSw!!mlg?7+8kYt4Uolwu6vWLqgmi^(_J{dJzUA%UfRvn8yIuu+L!)* znB&mV(h&tOYxjIl-G%X%S_3Yd@vlmtg!}<#>ow;TDd*}PxIe=bAJQd`z|FE$8U`4HmnBS2{VBCUAxz`>WO^-l!HZTN20^Pm z&esU2MMk@_nMOaIJRm}_r27?ffCeRCNn z`>f%fgM5oI=wRqAfBL)g{>;9Dq6Ill?3{nq zyS)yszh}+3x#X!VYhdpq5@|IO9#Nc~cb~g*V8WbPk4hU;IKB?+ zpJq`^Ns;1H0U>Rj`y$3j`%L+y=aYeInxEj14fsNnS4IQU@9l5p;S8TRQ}+6z`SM$f zNNw`)E%|KG=pNxQgTrXVHFcX2*wT(ouc}Qf2V|fuFPw9YQ|jUE;k7Go(%aJ`c!K0I z4Cip&SyK2uVID=CWOgIcF9v)Z#uy?J!dC0|wG3V5B%C|{(S_NH7|jAU6o z6bcXQXqh;w2rMC?cqND>ZHM#I^K8F8cPK7;!?c8{B9hmhx$k}HWqljf6>T=Bub@l`lc$_T5s>Nw>K|DBnWqMa zkGO*svE{9I8RAthN8R6GmH6HGL3o#<4w51Ima`iPEH(x!cxR+xcWo@Dk2 zV%cn*#jYX2QtzYP`;A{?@_!y4bVFHDeC)~=T94aJq->>atkbSZbd~QdW$=F{7pc|_ z_fQ(pw7GhB`-hT1BlTANRP1i<&4C4h`;fmVbZ6H=*cxe7Z6MoI0)!?PQ`S%7yP z2kl?)=krt4$a}B`@bq(}r!e32=~4ZRb6f!c@je4@*~zxo{xM02YM)h5>vb($J2!8;$8NmCBPY)*9UN+jJMM zm{|MrRzM8B-;k|ySUYVke1er-*9fjhsK&eG9>mu|%S73`u&E~{!e%*4O7uOuyecWo zV6Di!1^EOlYo489>%<8u@B-i3Qn@InjM-k#E{Y*_krZ)^H7>yz0eoFFsy~TW$nT#(;|*WpMYW?LioGGxrCINey^&Z?3r9htt< zm`zw3(rXoYRQ$@XN}zgY=Z%*I>^?YZ29gBbo?sOh9k9@5xrg$4xtw6Z-FdVJ+RBMdsW*$FDAG9FDJLP5v8!sjsNGx z1ZWK5p=1b0?+px*7@(NSH)9H*eJT3)7Zq{*DmZK`e~K3Ox+=-NVO4rF{T zk>YN|Ty4VM@r>t<7Qf4mc$JHPs!u_T08!zt;yZEs#770t?b&IDUO|o6uj&Mo()x?e zXbG0{Ei4(2zG2oUbUFqRzjm4XyyN~~Qd93xn%o&!v+)cr**6np%^jQNxZNh@{ZLgt zB6Ae$x+3IIq|#9*Mu(>%iSrC zm`l4jwR5vg<>)D1?s#1ix*AsyFECUyoLfw|`n1q=(i(t25;`_vWpBMnTDfVT?eInM zkGbS5F=XiLaN_o(7w&OyZb)_pu|B*ny=_Z*0fT=absX1W&mB$TwVYox?E9sUmh?@T z{arJh!FQe8f!u2MCS45Q!Md?v-`qA+K3*+mjA*yzU)aNMdc9t4ftPsoO`);aV*|RO zSi9c3z$tkv$iJN58R?e`v>_(>w5i0+|B+{OLz6>*3-g_b>deN7-*4srtgLtVfV0t} htn2?BX(&#Aa<7veuR7j-d=YRq5L$+smA7zD{s;e~O0fU{ literal 0 HcmV?d00001 diff --git a/demos/other/webgl-clear-color/index.html b/demos/other/webgl-clear-color/index.html new file mode 100644 index 0000000..762aa51 --- /dev/null +++ b/demos/other/webgl-clear-color/index.html @@ -0,0 +1,52 @@ + + + + + + VivaGraphs WebGL renderer clear color + + + + + + + + + From 233b307621be7b7c4f3d1d5e6f5ee55e6a1c287b Mon Sep 17 00:00:00 2001 From: Andrei Kashcha Date: Sun, 9 Nov 2014 15:38:32 -0800 Subject: [PATCH 103/276] Updated years --- LICENSE | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE b/LICENSE index add93fc..a1d90bf 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2011, Andrei Kashcha +Copyright (c) 2011 - 2014, Andrei Kashcha All rights reserved. Redistribution and use in source and binary forms, with or without @@ -23,4 +23,4 @@ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. From afcf573ce0aef5d7882c93e03c96fb25907e4fbe Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 26 Nov 2014 22:20:38 -0800 Subject: [PATCH 104/276] Updated link --- src/vivagraph.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vivagraph.js b/src/vivagraph.js index 18a71bb..e1faaac 100644 --- a/src/vivagraph.js +++ b/src/vivagraph.js @@ -1,5 +1,5 @@ /** - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ var Viva = Viva || {}; From ea49da27c777aa2302efd697200a14d915008f48 Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 26 Nov 2014 22:24:05 -0800 Subject: [PATCH 105/276] Fixed spelling --- src/View/cssGraphics.js | 7 ++++--- src/WebGL/webglImageNodeProgram.js | 8 ++++---- src/WebGL/webglLinkProgram.js | 4 ++-- src/WebGL/webglNodeProgram.js | 2 +- src/WebGL/webglUIModels.js | 10 +++++----- 5 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/View/cssGraphics.js b/src/View/cssGraphics.js index 0a2fe86..bfbe96a 100644 --- a/src/View/cssGraphics.js +++ b/src/View/cssGraphics.js @@ -2,6 +2,7 @@ * @fileOverview Defines a graph renderer that uses CSS based drawings. * * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * TODO: this should not be part of the library */ // The file tries to conform generic interface: /*jshint unused: false */ @@ -10,10 +11,10 @@ Viva.Graph.View = Viva.Graph.View || {}; /** * Performs css-based graph rendering. This module does not perform - * layout, but only visualizes nodes and edeges of the graph. + * layout, but only visualizes nodes and edges of the graph. * - * NOTE: Most likely I will remove this graphics engine due to superior svg support. - * In certain cases it doesn't work and require further imporvments: + * NOTE: Most likely I will remove this graphics engine due to superior SVG support. + * In certain cases it doesn't work and require further improvements: * * does not properly work for dragging. * * does not support scaling. * * does not support IE versions prior to IE9. diff --git a/src/WebGL/webglImageNodeProgram.js b/src/WebGL/webglImageNodeProgram.js index f8741c8..0dab89e 100644 --- a/src/WebGL/webglImageNodeProgram.js +++ b/src/WebGL/webglImageNodeProgram.js @@ -1,6 +1,6 @@ /** * @fileOverview Defines an image nodes for webglGraphics class. - * Shape of nodes is sqare. + * Shape of nodes is square. * * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com */ @@ -17,7 +17,7 @@ Viva.Graph.View.Texture = function (size) { /** * My naive implementation of textures atlas. It allows clients to load - * multimple images into atlas and get canvas representing all of them. + * multiple images into atlas and get canvas representing all of them. * * @param tilesPerTexture - indicates how many images can be loaded to one * texture of the atlas. If number of loaded images exceeds this @@ -122,7 +122,7 @@ Viva.Graph.View.webglAtlas = function (tilesPerTexture) { }, /** - * Removes given url from colleciton of tiles in the atlas. + * Removes given url from collection of tiles in the atlas. */ remove : function (imgUrl) { var coordinates = loadedImages[imgUrl]; @@ -416,4 +416,4 @@ Viva.Graph.View.webglImageNodeProgram = function () { gl.drawArrays(gl.TRIANGLES, 0, nodesCount * 6); } }; -}; \ No newline at end of file +}; diff --git a/src/WebGL/webglLinkProgram.js b/src/WebGL/webglLinkProgram.js index 091dcf9..a1dc438 100644 --- a/src/WebGL/webglLinkProgram.js +++ b/src/WebGL/webglLinkProgram.js @@ -2,8 +2,8 @@ * @fileOverview Defines a naive form of links for webglGraphics class. * This form allows to change color of links. * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com - */ + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka + **/ /** * Defines UI for links in webgl renderer. diff --git a/src/WebGL/webglNodeProgram.js b/src/WebGL/webglNodeProgram.js index f5f0110..5162f19 100644 --- a/src/WebGL/webglNodeProgram.js +++ b/src/WebGL/webglNodeProgram.js @@ -2,7 +2,7 @@ * @fileOverview Defines a naive form of nodes for webglGraphics class. * This form allows to change color of node. Shape of nodes is rectangular. * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ /** diff --git a/src/WebGL/webglUIModels.js b/src/WebGL/webglUIModels.js index ea0ad31..5cb35b2 100644 --- a/src/WebGL/webglUIModels.js +++ b/src/WebGL/webglUIModels.js @@ -2,7 +2,7 @@ * @fileOverview Defines a model objects to represents graph rendering * primitives in webglGraphics. * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ Viva.Graph.View.WebglUtils = function () { }; @@ -60,7 +60,7 @@ Viva.Graph.View.webglLine = function (color) { Viva.Graph.View.webglSquare = function (size, color) { return { /** - * Gets or sets size of the sqare side. + * Gets or sets size of the square side. */ size : typeof size === 'number' ? size : 10, @@ -77,7 +77,7 @@ Viva.Graph.View.webglSquare = function (size, color) { Viva.Graph.View.webglImage = function (size, src) { return { /** - * Gets texture index where current image is placed.s + * Gets texture index where current image is placed. */ _texture : 0, @@ -92,10 +92,10 @@ Viva.Graph.View.webglImage = function (size, src) { size : typeof size === 'number' ? size : 32, /** - * Source of the image. If image is comming not from your domain + * Source of the image. If image is coming not from your domain * certain origin restrictions applies. * See http://www.khronos.org/registry/webgl/specs/latest/#4.2 for more details. */ src : src }; -}; \ No newline at end of file +}; From 3450728ed1747a6ce73398026cbdd58892b76aa7 Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 26 Nov 2014 22:42:27 -0800 Subject: [PATCH 106/276] I enabled spell checker in vim... Fixing all typos. --- README.md | 2 +- src/Algorithms/Community/community.js | 12 +++++----- src/Algorithms/Community/slpa.js | 18 +++++++-------- src/Algorithms/centrality.js | 32 +++++++++++++-------------- src/Core/generator.js | 4 ++-- src/Core/graph.js | 12 +++++----- src/Core/operations.js | 4 ++-- src/Core/primitives.js | 2 +- src/Input/domInputManager.js | 2 +- src/Input/dragndrop.js | 2 +- src/Input/webglInputManager.js | 2 +- src/Layout/forceDirected.js | 12 +++++----- src/Physics/Forces/nbodyForce.js | 10 ++++----- src/Physics/forceSimulator.js | 2 +- src/Svg/svg.js | 2 +- src/Utils/etc.js | 6 ++--- src/Utils/events.js | 10 ++++----- src/Utils/geom.js | 6 ++--- src/Utils/indexOf.js | 2 +- src/View/cssGraphics.js | 6 ++--- src/View/renderer.js | 8 +++---- src/View/svgGraphics.js | 16 +++++++------- src/View/svgNodeFactory.js | 4 ++-- src/View/webglGraphics.js | 22 +++++++++--------- 24 files changed, 99 insertions(+), 99 deletions(-) diff --git a/README.md b/README.md index ecaa213..b5b903d 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ it supports rendering graphs using WebGL, SVG or CSS formats. **Note:** Please visit [anvaka/ngraph](https://github.com/anvaka/ngraph) to check next evolution step of this library. `ngraph` supports rendering graphs to images, -3d graphs rendering, integration with [gephi](https://gephi.org/) and more. +3D graphs rendering, integration with [gephi](https://gephi.org/) and more. Enough talking. Show me the demo! diff --git a/src/Algorithms/Community/community.js b/src/Algorithms/Community/community.js index c5d182f..5e256b0 100644 --- a/src/Algorithms/Community/community.js +++ b/src/Algorithms/Community/community.js @@ -1,23 +1,23 @@ /** * @fileOverview Community structure detection algorithms - * + * * @see http://en.wikipedia.org/wiki/Community_structure * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ Viva.Graph.community = function () { return { /** * Implementation of Speaker-listener Label Propagation Algorithm (SLPA) of - * Jierui Xie and Boleslaw K. Szymanski. - * + * Jierui Xie and Boleslaw K. Szymanski. + * * @see http://arxiv.org/pdf/1109.5720v3.pdf - * @see https://sites.google.com/site/communitydetectionslpa/ + * @see https://sites.google.com/site/communitydetectionslpa/ */ slpa : function (graph, T, r) { var algorithm = Viva.Graph._community.slpaAlgorithm(graph, T, r); return algorithm.run(); } }; -}; \ No newline at end of file +}; diff --git a/src/Algorithms/Community/slpa.js b/src/Algorithms/Community/slpa.js index 33259bc..8cf7213 100644 --- a/src/Algorithms/Community/slpa.js +++ b/src/Algorithms/Community/slpa.js @@ -130,7 +130,7 @@ Viva.Graph._community.slpaAlgorithm = function (graph, T, r) { * A data structure which serves as node memory during SLPA execution. The main idea is to * simplify operations on memory such as * - add word to memory, - * - get random word from memory, with probablity proportional to word occurrence in the memory + * - get random word from memory, with probability proportional to word occurrence in the memory * - get the most popular word in memory * * TODO: currently this structure is extremely inefficient in terms of memory. I think it could be @@ -160,9 +160,9 @@ Viva.Graph._community.occuranceMap = function (random) { return result; } - // Not only number of occurances matters but order of keys also does. + // Not only number of occurrences matters but order of keys also does. // for ... in implementation in different browsers results in different - // order, and if we want to have same categories accross all browsers + // order, and if we want to have same categories across all browsers // we should order words by key names too: if (x < y) { return -1; } if (x > y) { return 1; } @@ -196,7 +196,7 @@ Viva.Graph._community.occuranceMap = function (random) { }, /** - * Gets number of occurances for a given word. If word is not present in the dictionary + * Gets number of occurrences for a given word. If word is not present in the dictionary * zero is returned. */ getWordCount : function (word) { @@ -205,7 +205,7 @@ Viva.Graph._community.occuranceMap = function (random) { /** * Gets the most popular word in the map. If multiple words are at the same position - * random word among them is choosen. + * random word among them is chosen. * */ getMostPopularFair : function () { @@ -220,7 +220,7 @@ Viva.Graph._community.occuranceMap = function (random) { for (i = 1; i < uniqueWords.length; ++i) { if (wordsCount[uniqueWords[i - 1]] !== wordsCount[uniqueWords[i]]) { - break; // other words are less popular... not interested. + break; // other words are less popular... Not interested. } else { maxCount += 1; } @@ -236,7 +236,7 @@ Viva.Graph._community.occuranceMap = function (random) { */ getRandomWord : function () { if (allWords.length === 0) { - throw 'The occurance map is empty. Cannot get empty word'; + throw 'The occurrence map is empty. Cannot get empty word'; } return allWords[random.next(allWords.length)]; @@ -244,7 +244,7 @@ Viva.Graph._community.occuranceMap = function (random) { /** * Enumerates all unique words in the map, and calls - * callback(word, occuranceCount) function on each word. Callback + * callback(word, occurrenceCount) function on each word. Callback * can return true value to stop enumeration. * * Note: enumeration is guaranteed in to run in decreasing order. @@ -268,4 +268,4 @@ Viva.Graph._community.occuranceMap = function (random) { } } }; -}; \ No newline at end of file +}; diff --git a/src/Algorithms/centrality.js b/src/Algorithms/centrality.js index 783aec5..a3e87f3 100644 --- a/src/Algorithms/centrality.js +++ b/src/Algorithms/centrality.js @@ -1,16 +1,16 @@ /** - * @fileOverview Centrality calcuation algorithms. - * + * @fileOverview Centrality calculation algorithms. + * * @see http://en.wikipedia.org/wiki/Centrality * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ Viva.Graph.centrality = function () { var singleSourceShortestPath = function (graph, node, oriented) { // I'm using the same naming convention used in http://www.inf.uni-konstanz.de/algo/publications/b-fabc-01.pdf // sorry about cryptic names. - var P = {}, // predcessors lists. + var P = {}, // predecessors lists. S = [], sigma = {}, d = {}, @@ -101,26 +101,26 @@ Viva.Graph.centrality = function () { /** * Compute the shortest-path betweenness centrality for all nodes in a graph. - * - * Betweenness centrality of a node `n` is the sum of the fraction of all-pairs + * + * Betweenness centrality of a node `n` is the sum of the fraction of all-pairs * shortest paths that pass through `n`. Runtime O(n * v) for non-weighted graphs. * * @see http://en.wikipedia.org/wiki/Centrality#Betweenness_centrality - * - * @see A Faster Algorithm for Betweenness Centrality. + * + * @see A Faster Algorithm for Betweenness Centrality. * Ulrik Brandes, Journal of Mathematical Sociology 25(2):163-177, 2001. * http://www.inf.uni-konstanz.de/algo/publications/b-fabc-01.pdf - * - * @see Ulrik Brandes: On Variants of Shortest-Path Betweenness + * + * @see Ulrik Brandes: On Variants of Shortest-Path Betweenness * Centrality and their Generic Computation. * Social Networks 30(2):136-145, 2008. * http://www.inf.uni-konstanz.de/algo/publications/b-vspbc-08.pdf - * + * * @see Ulrik Brandes and Christian Pich: Centrality Estimation in Large Networks. * International Journal of Bifurcation and Chaos 17(7):2303-2318, 2007. * http://www.inf.uni-konstanz.de/algo/publications/bp-celn-06.pdf - * - * @param graph for which we are calculating betweenness centrality. Non-weighted graphs are only supported + * + * @param graph for which we are calculating betweenness centrality. Non-weighted graphs are only supported */ betweennessCentrality : function (graph) { var betweennes = {}, @@ -139,9 +139,9 @@ Viva.Graph.centrality = function () { /** * Calculates graph nodes degree centrality (in/out or both). - * + * * @see http://en.wikipedia.org/wiki/Centrality#Degree_centrality - * + * * @param graph for which we are calculating centrality. * @param kind optional parameter. Valid values are * 'in' - calculate in-degree centrality @@ -207,4 +207,4 @@ Viva.Graph.centrality = function () { return result; } }; -}; \ No newline at end of file +}; diff --git a/src/Core/generator.js b/src/Core/generator.js index 6f507b5..a2c32fc 100644 --- a/src/Core/generator.js +++ b/src/Core/generator.js @@ -1,7 +1,7 @@ /** * @fileOverview Contains collection of graph generators. * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ Viva.Graph.generator = function () { @@ -43,7 +43,7 @@ Viva.Graph.generator = function () { */ completeBipartite : function (n, m) { if (!n || !m || n < 0 || m < 0) { - throw { message: "Graph dimensions are invalid. Number of nodes in each partition should be greate than 0" }; + throw { message: "Graph dimensions are invalid. Number of nodes in each partition should be greater than 0" }; } var g = Viva.Graph.graph(), diff --git a/src/Core/graph.js b/src/Core/graph.js index 401c5a3..1ae401d 100644 --- a/src/Core/graph.js +++ b/src/Core/graph.js @@ -1,7 +1,7 @@ /** * @fileOverview Contains definition of the core graph object. * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ /** @@ -20,7 +20,7 @@ Viva.Graph.graph = function () { // hold all links related to that node. And general links // array is used to speed up all links enumeration. This is inefficient // in terms of memory, but simplifies coding. Furthermore, the graph structure - // is isolated from outter world, and can be changed to adjacency matrix later. + // is isolated from outer world, and can be changed to adjacency matrix later. var nodes = (typeof Object.create === 'function') ? Object.create(null) : {}, links = [], @@ -29,7 +29,7 @@ Viva.Graph.graph = function () { nodesCount = 0, suspendEvents = 0, - // Accumlates all changes made during graph updates. + // Accumulates all changes made during graph updates. // Each change element contains: // changeType - one of the strings: 'add', 'remove' or 'update'; // node - if change is related to node this property is set to changed graph's node; @@ -41,7 +41,7 @@ Viva.Graph.graph = function () { graph.fire('changed', changes); }, - // Enter, Exit Mofidication allows bulk graph updates without firing events. + // Enter, Exit modification allows bulk graph updates without firing events. enterModification = function () { suspendEvents += 1; }, @@ -270,7 +270,7 @@ Viva.Graph.graph = function () { // I.e. use array + 'for' iterator instead of dictionary + 'for .. in'? for (node in nodes) { if (callback(nodes[node])) { - return; // client doesn't want to proceed. return. + return; // client doesn't want to proceed. } } }, @@ -290,7 +290,7 @@ Viva.Graph.graph = function () { linkedNodeId; if (node && node.links && typeof callback === 'function') { - // Extraced orientation check out of the loop to increase performance + // Extracted orientation check out of the loop to increase performance if (oriented) { for (i = 0; i < node.links.length; ++i) { link = node.links[i]; diff --git a/src/Core/operations.js b/src/Core/operations.js index 6263883..9b01a67 100644 --- a/src/Core/operations.js +++ b/src/Core/operations.js @@ -1,7 +1,7 @@ /** - * @fileOverview Contains collection of primitve operations under graph. + * @fileOverview Contains collection of primitive operations under graph. * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ Viva.Graph.operations = function () { diff --git a/src/Core/primitives.js b/src/Core/primitives.js index 192250b..12889dc 100644 --- a/src/Core/primitives.js +++ b/src/Core/primitives.js @@ -1,5 +1,5 @@ /** - * Very generic rectangle. + * Very generic rectangle. */ Viva.Graph.Rect = function (x1, y1, x2, y2) { this.x1 = x1 || 0; diff --git a/src/Input/domInputManager.js b/src/Input/domInputManager.js index 18f6dc6..25d5865 100644 --- a/src/Input/domInputManager.js +++ b/src/Input/domInputManager.js @@ -1,5 +1,5 @@ /** - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ Viva.Input = Viva.Input || {}; diff --git a/src/Input/dragndrop.js b/src/Input/dragndrop.js index cd70c53..184df18 100644 --- a/src/Input/dragndrop.js +++ b/src/Input/dragndrop.js @@ -1,5 +1,5 @@ /** - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ Viva.Graph.Utils = Viva.Graph.Utils || {}; diff --git a/src/Input/webglInputManager.js b/src/Input/webglInputManager.js index 7be7771..a031095 100644 --- a/src/Input/webglInputManager.js +++ b/src/Input/webglInputManager.js @@ -1,5 +1,5 @@ /** - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ Viva.Input = Viva.Input || {}; diff --git a/src/Layout/forceDirected.js b/src/Layout/forceDirected.js index a03ab98..2e744c9 100644 --- a/src/Layout/forceDirected.js +++ b/src/Layout/forceDirected.js @@ -28,7 +28,7 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { gravity: -1.2, /** - * Theta coeffiecient from Barnes Hut simulation. Ranged between (0, 1). + * Theta coefficient from Barnes Hut simulation. Ranged between (0, 1). * The closer it's to 1 the more nodes algorithm will have to go through. * Setting it to one makes Barnes Hut simulation no different from * brute-force forces calculation (each node is considered). @@ -42,7 +42,7 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { dragCoeff: 0.02, /** - * Allows to transfor physical spring associated with a link. this allows clients + * Allows to transform physical spring associated with a link. This allows clients * to specify custom length for a link. * * @param {Viva.Graph.Link} link actual link for which transform is performed @@ -405,9 +405,9 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { }, /** - * Gets or sets current spring coeffiсient. + * Gets or sets current spring coefficient. * - * @param coeff new spring coeffiсient. + * @param coeff new spring coefficient. * if this parameter is empty then its old value returned. */ springCoeff: function(coeff) { @@ -441,7 +441,7 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { /** * Gets or sets current theta value in the nbody simulation. * - * @param t new theta coeffiсient. + * @param t new theta coefficient. * if this parameter is empty then its old value returned. */ theta: function(t) { @@ -458,7 +458,7 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { /** * Gets or sets current theta value in the nbody simulation. * - * @param dragCoeff new drag coeffiсient. + * @param dragCoeff new drag coefficient. * if this parameter is empty then its old value returned. */ drag: function(dragCoeff) { diff --git a/src/Physics/Forces/nbodyForce.js b/src/Physics/Forces/nbodyForce.js index f26ab80..32a2ed7 100644 --- a/src/Physics/Forces/nbodyForce.js +++ b/src/Physics/Forces/nbodyForce.js @@ -1,7 +1,7 @@ /** * This is Barnes Hut simulation algorithm. Implementation * is adopted to non-recursive solution, since certain browsers - * handle recursion extremly bad. + * handle recursion extremely bad. * * http://www.cs.princeton.edu/courses/archive/fall03/cs126/assignments/barnes-hut.html */ @@ -159,7 +159,7 @@ Viva.Graph.Physics.nbodyForce = function (options) { // To achieve this we have to convert current leaf into internal node // and continue adding two nodes. var oldBody = node.body; - node.body = null; // internal nodes do not cary bodies + node.body = null; // internal nodes do not carry bodies node.isInternal = true; if (isSamePosition(oldBody.location, body.location)) { @@ -223,13 +223,13 @@ Viva.Graph.Physics.nbodyForce = function (options) { r = Math.sqrt(dx * dx + dy * dy); if (r === 0) { - // Poor man's protection agains zero distance. + // Poor man's protection against zero distance. dx = (random.nextDouble() - 0.5) / 50; dy = (random.nextDouble() - 0.5) / 50; r = Math.sqrt(dx * dx + dy * dy); } - // This is standard gravition force calculation but we divide + // This is standard gravitation force calculation but we divide // by r^3 to save two operations when normalizing force vector. v = gravity * body.mass * sourceBody.mass / (r * r * r); sourceBody.force.x = sourceBody.force.x + v * dx; @@ -243,7 +243,7 @@ Viva.Graph.Physics.nbodyForce = function (options) { r = Math.sqrt(dx * dx + dy * dy); if (r === 0) { - // Sorry about code duplucation. I don't want to create many functions + // Sorry about code duplication. I don't want to create many functions // right away. Just want to see performance first. dx = (random.nextDouble() - 0.5) / 50; dy = (random.nextDouble() - 0.5) / 50; diff --git a/src/Physics/forceSimulator.js b/src/Physics/forceSimulator.js index 8cf6ee5..f3894ba 100644 --- a/src/Physics/forceSimulator.js +++ b/src/Physics/forceSimulator.js @@ -3,7 +3,7 @@ Viva.Graph.Physics = Viva.Graph.Physics || {}; /** * Manages a simulation of physical forces acting on bodies. * To create a custom force simulator register forces of the system - * via addForce() method, choos appropriate integrator and register + * via addForce() method, choose appropriate integrator and register * bodies. * * // TODO: Show example. diff --git a/src/Svg/svg.js b/src/Svg/svg.js index 0a22809..8fa4d8f 100644 --- a/src/Svg/svg.js +++ b/src/Svg/svg.js @@ -1,5 +1,5 @@ /** - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ /** diff --git a/src/Utils/etc.js b/src/Utils/etc.js index 2fcd74b..54a6e1c 100644 --- a/src/Utils/etc.js +++ b/src/Utils/etc.js @@ -26,7 +26,7 @@ Viva.lazyExtend = function (target, options) { return target; }; /** - * Implenetation of seeded pseudo random number generator, based on Robert Jenkin's 32 bit integer hash function + * Implementation of seeded pseudo random number generator, based on Robert Jenkin's 32 bit integer hash function * * Usage example: * var random = Viva.random(seedNumber), @@ -58,7 +58,7 @@ Viva.random = function () { /** * Generates random integer number in the range from 0 (inclusive) to maxValue (exclusive) * - * @param maxValue is REQUIRED. Ommitit this numbe will result in NaN values from PRNG. + * @param maxValue is REQUIRED. Omitting this number will result in NaN values from PRNG. */ next : function (maxValue) { return Math.floor(randomFunc() * maxValue); @@ -82,7 +82,7 @@ Viva.random = function () { * * @param array to be shuffled * @param random - a [seeded] random number generator to produce same sequences. This parameter - * is optional. If you don't need determenistic randomness keep it blank. + * is optional. If you don't need deterministic randomness keep it blank. */ Viva.randomIterator = function (array, random) { random = random || Viva.random(); diff --git a/src/Utils/events.js b/src/Utils/events.js index 3670775..a930eed 100644 --- a/src/Utils/events.js +++ b/src/Utils/events.js @@ -1,5 +1,5 @@ /** - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ Viva.Graph.Utils = Viva.Graph.Utils || {}; @@ -8,7 +8,7 @@ Viva.Graph.Utils = Viva.Graph.Utils || {}; // hard to understand. Refactor it. // TODO: This is really painful. Please don't use this class anymore, I will -// definitely depricate it or update its interface. +// definitely deprecate it or update its interface. /** * Allows to start/stop listen to element's events. An element can be arbitrary @@ -27,7 +27,7 @@ Viva.Graph.Utils.events = function (element) { * This behavior is based on Crockford's eventuality example, but with a minor changes: * - fire() method accepts parameters to pass to callbacks (instead of setting them in 'on' method) * - on() method is replaced with addEventListener(), to let objects be used as a DOM objects. - * - behavoir contract is simplified to "string as event name"/"function as callback" convention. + * - behavior contract is simplified to "string as event name"/"function as callback" convention. * - removeEventListener() method added to let unsubscribe from events. */ var eventuality = function (that) { @@ -113,10 +113,10 @@ Viva.Graph.Utils.events = function (element) { return { /** - * Registes callback to be called when element fires event with given event name. + * Registers callback to be called when element fires event with given event name. */ on : function (eventName, callback) { - if (element.addEventListener) {// W3C DOM and eventuality objecets. + if (element.addEventListener) {// W3C DOM and eventuality objects. element.addEventListener(eventName, callback, false); } else if (element.attachEvent) { // IE DOM element.attachEvent("on" + eventName, callback); diff --git a/src/Utils/geom.js b/src/Utils/geom.js index 4c4117a..75d9c82 100644 --- a/src/Utils/geom.js +++ b/src/Utils/geom.js @@ -27,7 +27,7 @@ Viva.Graph.geom = function () { */ if (r3 !== 0 && r4 !== 0 && ((r3 >= 0) === (r4 >= 4))) { - return null; //no itersection. + return null; //no intersection. } /* Compute a2, b2, c2 */ @@ -92,7 +92,7 @@ Viva.Graph.geom = function () { dy = p.y - basePoint.y, sign = dx > 0 ? 1 : -1; - // We use squared dx, to avoid Sqrt opertion and improve performance. + // We use squared dx, to avoid Sqrt operation and improve performance. // To avoid sign loss during dx * dx operation we precompute its sign: return sign * dx * dx / (dx * dx + dy * dy); }, @@ -183,4 +183,4 @@ Viva.Graph.geom = function () { return s; } }; -}; \ No newline at end of file +}; diff --git a/src/Utils/indexOf.js b/src/Utils/indexOf.js index 7f65044..384ef66 100644 --- a/src/Utils/indexOf.js +++ b/src/Utils/indexOf.js @@ -1,5 +1,5 @@ /** - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ Viva.Graph.Utils = Viva.Graph.Utils || {}; diff --git a/src/View/cssGraphics.js b/src/View/cssGraphics.js index bfbe96a..d6b37c8 100644 --- a/src/View/cssGraphics.js +++ b/src/View/cssGraphics.js @@ -78,7 +78,7 @@ Viva.Graph.View.cssGraphics = function () { // IE 6, 7 and 8 are screwed up when it comes to transforms; // I could not find justification for their choice of "floating" // matrix transform origin. The following ugly code was written - // out of complete dispair. + // out of complete despair. if (angleRad < 0) { angleRad = 2 * Math.PI + angleRad; } @@ -158,7 +158,7 @@ Viva.Graph.View.cssGraphics = function () { return { /** - * Sets the collback that creates node representation or creates a new node + * Sets the callback that creates node representation or creates a new node * presentation if builderCallbackOrNode is not a function. * * @param builderCallbackOrNode a callback function that accepts graph node @@ -179,7 +179,7 @@ Viva.Graph.View.cssGraphics = function () { }, /** - * Sets the collback that creates link representation or creates a new link + * Sets the callback that creates link representation or creates a new link * presentation if builderCallbackOrLink is not a function. * * @param builderCallbackOrLink a callback function that accepts graph link diff --git a/src/View/renderer.js b/src/View/renderer.js index bb84d23..3fb3723 100644 --- a/src/View/renderer.js +++ b/src/View/renderer.js @@ -1,7 +1,7 @@ /** * @fileOverview Defines a graph renderer that uses CSS based drawings. * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ Viva.Graph.View = Viva.Graph.View || {}; @@ -38,14 +38,14 @@ Viva.Graph.View = Viva.Graph.View || {}; * renderLinks : true, * * // Number of layout iterations to run before displaying the graph. The bigger you set this number - * // the closer to ideal position graph will apper first time. But be careful: for large graphs + * // the closer to ideal position graph will appear first time. But be careful: for large graphs * // it can freeze the browser. * prerender : 0 * } */ Viva.Graph.View.renderer = function (graph, settings) { // TODO: This class is getting hard to understand. Consider refactoring. - // TODO: I have a technical debt here: fix scaling/recentring! Currently it's total mess. + // TODO: I have a technical debt here: fix scaling/recentering! Currently it's a total mess. var FRAME_INTERVAL = 30; settings = settings || {}; @@ -293,7 +293,7 @@ Viva.Graph.View.renderer = function (graph, settings) { releaseGraphEvents = function () { if (graphEvents) { - // Interesting.. why is it not null? Anyway: + // Interesting.. Why is it not null? Anyway: graphEvents.stop('changed', onGraphChanged); graphEvents = null; } diff --git a/src/View/svgGraphics.js b/src/View/svgGraphics.js index 9e2b511..0897fb9 100644 --- a/src/View/svgGraphics.js +++ b/src/View/svgGraphics.js @@ -8,7 +8,7 @@ Viva.Graph.View = Viva.Graph.View || {}; /** * Performs svg-based graph rendering. This module does not perform - * layout, but only visualizes nodes and edeges of the graph. + * layout, but only visualizes nodes and edges of the graph. */ Viva.Graph.View.svgGraphics = function () { var svgContainer, @@ -28,7 +28,7 @@ Viva.Graph.View.svgGraphics = function () { }, nodePositionCallback = function (nodeUI, pos) { - // TODO: Remove magic 5. It should be halfo of the width or height of the node. + // TODO: Remove magic 5. It should be half of the width or height of the node. nodeUI.attr("x", pos.x - 5) .attr("y", pos.y - 5); }, @@ -83,7 +83,7 @@ Viva.Graph.View.svgGraphics = function () { */ node : function (builderCallback) { if (typeof builderCallback !== "function") { - return; // todo: throw? this is not compatible with old versions + return; // todo: throw? This is not compatible with old versions } nodeBuilder = builderCallback; @@ -98,11 +98,11 @@ Viva.Graph.View.svgGraphics = function () { * as a parameter and must return an element representing this link. * * @returns If builderCallback is a valid callback function, instance of this is returned; - * Otherwise undefined value is returend. + * Otherwise undefined value is returned. */ link : function (builderCallback) { if (typeof builderCallback !== "function") { - return; // todo: throw? this is not compatible with old versions + return; // todo: throw? This is not compatible with old versions } linkBuilder = builderCallback; @@ -172,7 +172,7 @@ Viva.Graph.View.svgGraphics = function () { p.x = scrollPoint.x; p.y = scrollPoint.y; - p = p.matrixTransform(svgContainer.getCTM().inverse()); // translate to svg coordinates + p = p.matrixTransform(svgContainer.getCTM().inverse()); // translate to SVG coordinates // Compute new scale matrix in current mouse position var k = svgRoot.createSVGMatrix().translate(p.x, p.y).scale(scaleFactor).translate(-p.x, -p.y), @@ -203,7 +203,7 @@ Viva.Graph.View.svgGraphics = function () { init : function (container) { container.appendChild(svgRoot); updateTransform(); - // Notify the world if someoen waited for update. TODO: should send an event + // Notify the world if someone waited for update. TODO: should send an event if (typeof initCallback === "function") { initCallback(svgRoot); } @@ -326,7 +326,7 @@ Viva.Graph.View.svgGraphics = function () { return svgRoot; }, /** - * Returns root svg element. + * Returns root SVG element. * * Note: This is internal method specific to this renderer */ diff --git a/src/View/svgNodeFactory.js b/src/View/svgNodeFactory.js index 3edcd92..102750b 100644 --- a/src/View/svgNodeFactory.js +++ b/src/View/svgNodeFactory.js @@ -4,7 +4,7 @@ * but I'm not happy with the code result here. Probably this class * will be removed from future versions. * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ Viva.Graph.View.svgNodeFactory = function (graph) { @@ -49,7 +49,7 @@ Viva.Graph.View.svgNodeFactory = function (graph) { }, /** - * Sets a callback function for custom nodes contnet. + * Sets a callback function for custom nodes content. * @param conentCreator(nodeUI, node) - callback function which returns a node content UI. * Image, for example. * @param sizeProvider(nodeUI) - a callback function which accepts nodeUI returned by diff --git a/src/View/webglGraphics.js b/src/View/webglGraphics.js index ec36dd1..61ea421 100644 --- a/src/View/webglGraphics.js +++ b/src/View/webglGraphics.js @@ -1,14 +1,14 @@ /** * @fileOverview Defines a graph renderer that uses WebGL based drawings. * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ Viva.Graph.View = Viva.Graph.View || {}; /** * Performs webgl-based graph rendering. This module does not perform - * layout, but only visualizes nodes and edeges of the graph. + * layout, but only visualizes nodes and edges of the graph. * * @param options - to customize graphics behavior. Currently supported parameter * enableBlending - true by default, allows to use transparency in node/links colors. @@ -99,7 +99,7 @@ Viva.Graph.View.webglGraphics = function (options) { }, /** - * Sets the collback that creates node representation. + * Sets the callback that creates node representation. * * @param builderCallback a callback function that accepts graph node * as a parameter and must return an element representing this node. @@ -109,7 +109,7 @@ Viva.Graph.View.webglGraphics = function (options) { */ node : function (builderCallback) { if (typeof builderCallback !== "function") { - return; // todo: throw? this is not compatible with old versions + return; // todo: throw? This is not compatible with old versions } nodeUIBuilder = builderCallback; @@ -124,11 +124,11 @@ Viva.Graph.View.webglGraphics = function (options) { * as a parameter and must return an element representing this link. * * @returns If builderCallback is a valid callback function, instance of this is returned; - * Otherwise undefined value is returend. + * Otherwise undefined value is returned. */ link : function (builderCallback) { if (typeof builderCallback !== "function") { - return; // todo: throw? this is not compatible with old versions + return; // todo: throw? This is not compatible with old versions } linkUIBuilder = builderCallback; @@ -314,7 +314,7 @@ Viva.Graph.View.webglGraphics = function (options) { var color = options.clearColorValue; gl.clearColor(color.r, color.g, color.b, color.a); // TODO: not the best way, really. Should come up with something better - // what if we need more updates inisde beginRender, like depth buffer? + // what if we need more updates inside beginRender, like depth buffer? this.beginRender = function () { gl.clear(gl.COLOR_BUFFER_BIT); }; @@ -328,7 +328,7 @@ Viva.Graph.View.webglGraphics = function (options) { updateTransformUniform(); - // Notify the world if someoen waited for update. TODO: should send an event + // Notify the world if someone waited for update. TODO: should send an event if (typeof initCallback === "function") { initCallback(graphicsRoot); } @@ -403,7 +403,7 @@ Viva.Graph.View.webglGraphics = function (options) { nodes[nodeIdToRemove] = lastNodeUI; lastNodeUI.id = nodeIdToRemove; - // Since concrete shaders may cache properties in the ui element + // Since concrete shaders may cache properties in the UI element // we are letting them to make this swap (e.g. image node shader // uses this approach to update node's offset in the atlas) nodeProgram.replaceProperties(nodeUI, lastNodeUI); @@ -474,7 +474,7 @@ Viva.Graph.View.webglGraphics = function (options) { // and let initialization logic take care about the rest. nodeProgram = newProgram; } else if (newProgram) { - throw "Not implemented. Cannot swap shader on the fly... yet."; + throw "Not implemented. Cannot swap shader on the fly... Yet."; // TODO: unload old shader and reinit. } }, @@ -490,7 +490,7 @@ Viva.Graph.View.webglGraphics = function (options) { // and let initialization logic take care about the rest. linkProgram = newProgram; } else if (newProgram) { - throw "Not implemented. Cannot swap shader on the fly... yet."; + throw "Not implemented. Cannot swap shader on the fly... Yet."; // TODO: unload old shader and reinit. } }, From 9075454b4924c6a441d6d456a32ccf5c70f13f19 Mon Sep 17 00:00:00 2001 From: anvaka Date: Thu, 4 Dec 2014 21:36:46 -0800 Subject: [PATCH 107/276] Added demo with circular images --- demos/other/svg-circle-images/README.md | 20 ++++++ demos/other/svg-circle-images/index.html | 28 ++++++++ demos/other/svg-circle-images/index.js | 92 ++++++++++++++++++++++++ 3 files changed, 140 insertions(+) create mode 100644 demos/other/svg-circle-images/README.md create mode 100644 demos/other/svg-circle-images/index.html create mode 100644 demos/other/svg-circle-images/index.js diff --git a/demos/other/svg-circle-images/README.md b/demos/other/svg-circle-images/README.md new file mode 100644 index 0000000..f9d8432 --- /dev/null +++ b/demos/other/svg-circle-images/README.md @@ -0,0 +1,20 @@ +# Render nodes as circular images + +This demo shows how to implement circular images with SVG renderer. [Click here](http://anvaka.github.io/VivaGraphJS/demos/other/svg-circle-images/) to see it in action. + +# How it is done? + +We are using [SVG Patterns](http://www.w3.org/TR/SVG/pservers.html#Patterns) to +fill a circle with Image brush. The `graphics.node()` function reconstructs +structure similar to the following: + +``` html + + + + + + + + +``` diff --git a/demos/other/svg-circle-images/index.html b/demos/other/svg-circle-images/index.html new file mode 100644 index 0000000..eb01487 --- /dev/null +++ b/demos/other/svg-circle-images/index.html @@ -0,0 +1,28 @@ + + + + + + VivaGraphs SVG circle images + + + + + + + + +

+ + + diff --git a/demos/other/svg-circle-images/index.js b/demos/other/svg-circle-images/index.js new file mode 100644 index 0000000..cd8b525 --- /dev/null +++ b/demos/other/svg-circle-images/index.js @@ -0,0 +1,92 @@ +/** + * This demo shows one possible way of implementing nodes as circular images + */ +function onLoad() { + var graphics = Viva.Graph.View.svgGraphics(); + + // we will use SVG patterns to fill circle with image brush: + // http://stackoverflow.com/questions/11496734/add-a-background-image-png-to-a-svg-circle-shape + var defs = Viva.Graph.svg('defs'); + graphics.getSvgRoot().append(defs); + + graphics.node(createNodeWithImage) + .placeNode(placeNodeWithTransform); + + var graph = constructGraph(); + var renderer = Viva.Graph.View.renderer(graph, { + graphics: graphics, + container: document.getElementById('graph-container') + }); + + renderer.run(); + + function createNodeWithImage(node) { + var radius = 12; + // First, we create a fill pattern and add it to SVG's defs: + var pattern = Viva.Graph.svg('pattern') + .attr('id', "imageFor_" + node.id) + .attr('patternUnits', "userSpaceOnUse") + .attr('width', 100) + .attr('height', 100) + var image = Viva.Graph.svg('image') + .attr('x', '0') + .attr('y', '0') + .attr('height', radius * 2) + .attr('width', radius * 2) + .link(node.data.url); + pattern.append(image); + defs.append(pattern); + + // now create actual node and reference created fill pattern: + var ui = Viva.Graph.svg('g'); + var circle = Viva.Graph.svg('circle') + .attr('cx', radius) + .attr('cy', radius) + .attr('fill', 'url(#imageFor_' + node.id + ')') + .attr('r', radius); + + ui.append(circle); + return ui; + } + + function placeNodeWithTransform(nodeUI, pos) { + // Shift image to let links go to the center: + nodeUI.attr('transform', 'translate(' + (pos.x - 12) + ',' + (pos.y - 12) + ')'); + } +} + + +function constructGraph() { + var graph = Viva.Graph.graph(); + + graph.addNode('anvaka', { + url: 'https://secure.gravatar.com/avatar/91bad8ceeec43ae303790f8fe238164b' + }); + graph.addNode('manunt', { + url: 'https://secure.gravatar.com/avatar/c81bfc2cf23958504617dd4fada3afa8' + }); + graph.addNode('thlorenz', { + url: 'https://secure.gravatar.com/avatar/1c9054d6242bffd5fd25ec652a2b79cc' + }); + graph.addNode('bling', { + url: 'https://secure.gravatar.com/avatar/24a5b6e62e9a486743a71e0a0a4f71af' + }); + graph.addNode('diyan', { + url: 'https://secure.gravatar.com/avatar/01bce7702975191fdc402565bd1045a8?' + }); + graph.addNode('pocheptsov', { + url: 'https://secure.gravatar.com/avatar/13da974fc9716b42f5d62e3c8056c718' + }); + graph.addNode('dimapasko', { + url: 'https://secure.gravatar.com/avatar/8e587a4232502a9f1ca14e2810e3c3dd' + }); + + graph.addLink('anvaka', 'manunt'); + graph.addLink('anvaka', 'thlorenz'); + graph.addLink('anvaka', 'bling'); + graph.addLink('anvaka', 'diyan'); + graph.addLink('anvaka', 'pocheptsov'); + graph.addLink('anvaka', 'dimapasko'); + + return graph; +} From cea9400f89ad270326c72e8043e2243dc16f5446 Mon Sep 17 00:00:00 2001 From: Andrei Kashcha Date: Thu, 4 Dec 2014 21:39:04 -0800 Subject: [PATCH 108/276] Update README.md --- demos/other/svg-circle-images/README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/demos/other/svg-circle-images/README.md b/demos/other/svg-circle-images/README.md index f9d8432..dea07c3 100644 --- a/demos/other/svg-circle-images/README.md +++ b/demos/other/svg-circle-images/README.md @@ -12,9 +12,12 @@ structure similar to the following: - + ``` + +See [source code](https://github.com/anvaka/VivaGraphJS/blob/9075454b4924c6a441d6d456a32ccf5c70f13f19/demos/other/svg-circle-images/index.js#L23) for exact steps. From 304d7777e8df32b1dda50f55d4d4ef576fa9f4bb Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 27 Dec 2014 11:35:32 -0800 Subject: [PATCH 109/276] Migrated to gulp --- .jshintrc | 1 - CHANGELOG | 4 + Gruntfile.js | 145 ---------------------- dist/vivagraph.js | 280 ++++++++++++++++++++++++------------------ dist/vivagraph.min.js | 4 +- gulpfile.js | 85 +++++++++++++ package.json | 12 +- src/version.js | 2 +- 8 files changed, 261 insertions(+), 272 deletions(-) delete mode 100644 Gruntfile.js create mode 100644 gulpfile.js diff --git a/.jshintrc b/.jshintrc index c59ae7c..604b7d3 100644 --- a/.jshintrc +++ b/.jshintrc @@ -8,7 +8,6 @@ "curly": true, "eqeqeq": true, "immed": true, - "indent": 4, "latedef": false, "newcap": true, "noarg": true, diff --git a/CHANGELOG b/CHANGELOG index 4d627dd..304614a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,7 @@ +v0.6.0 + date Dec 27, 2014 + - Migrated to gulp. First step towards commonjs. + - Fixed spelling, grammar. v0.5.8 date: Sep 28, 2014 - Graphics object no longer waits `init` method to create container. Fixes diff --git a/Gruntfile.js b/Gruntfile.js deleted file mode 100644 index c7cdb18..0000000 --- a/Gruntfile.js +++ /dev/null @@ -1,145 +0,0 @@ -// Generated on 2013-03-27 using generator-webapp 0.1.5 -"use strict"; - -module.exports = function (grunt) { - var libConfig = { - src: "src", - dist: "dist" - }; - // This needs to be changed. It"s just copies structure of - // my original builder, which was not really well organized: - var fileGroups = { - core: [ - "vivagraph.js", - "version.js", - "Utils/etc.js", - "Utils/browserInfo.js", - "Utils/indexOf.js", - "Utils/getDimensions.js", - "Utils/events.js", - "Input/dragndrop.js", - "Input/domInputManager.js", - "Input/spatialIndex.js", // TODO: Do I need this for SVG? - "Utils/timer.js", - "Utils/geom.js", - - "Core/primitives.js", - "Core/graph.js", - "Core/operations.js", - - "Physics/primitives.js", - "Physics/eulerIntegrator.js", - "Physics/Forces/nbodyForce.js", - "Physics/Forces/dragForce.js", - "Physics/Forces/springForce.js", - "Physics/forceSimulator.js", - "Layout/forceDirected.js", - "Layout/constant.js", - "View/renderer.js" - ], - extra: [ - "Core/serializer.js", - "Algorithms/centrality.js", - "Algorithms/Community/community.js", - "Algorithms/Community/slpa.js", - "Core/generator.js", - "View/cssGraphics.js" - ], - svg: [ - "Svg/svg.js", - "View/svgGraphics.js", - "View/svgNodeFactory.js", - ], - webgl: [ - "WebGL/webgl.js", - "WebGL/webglUIModels.js", - "WebGL/webglNodeProgram.js", - "WebGL/webglLinkProgram.js", - "WebGL/webglImageNodeProgram.js", - "View/webglGraphics.js", - "WebGL/webglInputEvents.js", - "Input/webglInputManager.js", - ] - }; - Object.keys(fileGroups).forEach(function (key) { - fileGroups[key] = fileGroups[key].map(function (path) { - return libConfig.src + "/" + path; - }); - }); - grunt.initConfig({ - lib: libConfig, - watch: { - js: { - files: "<%= lib.src %>/**/*.js", - tasks: ["build"], - spawn: true - } - }, - jshint: { - all: [ - "Gruntfile.js", - "<%= lib.src %>/{,*/}*.js" - ], - options: { - jshintrc: ".jshintrc" - } - }, - clean: { - dist: ["<%= lib.dist %>/*"], - }, - concat: { - options: { - separator: "" - }, - all: { - src: [ - fileGroups.core, - fileGroups.extra, - fileGroups.svg, - fileGroups.webgl - ], - dest: "<%= lib.dist %>/vivagraph.js" - }, - svg: { - src: [ - fileGroups.core, - fileGroups.svg - ], - dest: "<%= lib.dist %>/vivagraph.svg.js" - }, - webgl: { - src: [ - fileGroups.core, - fileGroups.webgl - ], - dest: "<%= lib.dist %>/vivagraph.webgl.js" - }, - }, - uglify: { - dist: { - files: { - "<%= lib.dist %>/vivagraph.min.js": ["<%= lib.dist %>/vivagraph.js"] - } - } - } - }); - - grunt.loadNpmTasks("grunt-contrib-clean"); - grunt.loadNpmTasks("grunt-contrib-jshint"); - grunt.loadNpmTasks("grunt-contrib-concat"); - grunt.loadNpmTasks("grunt-contrib-uglify"); - grunt.loadNpmTasks("grunt-regarde"); - - grunt.renameTask("regarde", "watch"); - - grunt.registerTask("build", [ - "clean:dist", - "concat:all", - "uglify" - ]); - grunt.registerTask("server", [ - "build", - "watch" - ]); - grunt.registerTask("default", ["jshint", "build"]); -}; diff --git a/dist/vivagraph.js b/dist/vivagraph.js index b566dff..c23fde4 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -1,5 +1,5 @@ /** - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ var Viva = Viva || {}; @@ -7,7 +7,9 @@ Viva.Graph = Viva.Graph || {}; if (typeof module !== 'undefined' && module.exports) { module.exports = Viva; } -Viva.Graph.version = '0.5.8'; + +Viva.Graph.version = '0.6.0'; + /** * Extends target object with given fields/values in the options object. * Unlike jQuery's extend this method does not override target object @@ -36,7 +38,7 @@ Viva.lazyExtend = function (target, options) { return target; }; /** - * Implenetation of seeded pseudo random number generator, based on Robert Jenkin's 32 bit integer hash function + * Implementation of seeded pseudo random number generator, based on Robert Jenkin's 32 bit integer hash function * * Usage example: * var random = Viva.random(seedNumber), @@ -68,7 +70,7 @@ Viva.random = function () { /** * Generates random integer number in the range from 0 (inclusive) to maxValue (exclusive) * - * @param maxValue is REQUIRED. Ommitit this numbe will result in NaN values from PRNG. + * @param maxValue is REQUIRED. Omitting this number will result in NaN values from PRNG. */ next : function (maxValue) { return Math.floor(randomFunc() * maxValue); @@ -92,7 +94,7 @@ Viva.random = function () { * * @param array to be shuffled * @param random - a [seeded] random number generator to produce same sequences. This parameter - * is optional. If you don't need determenistic randomness keep it blank. + * is optional. If you don't need deterministic randomness keep it blank. */ Viva.randomIterator = function (array, random) { random = random || Viva.random(); @@ -130,6 +132,7 @@ Viva.randomIterator = function (array, random) { } }; }; + Viva.BrowserInfo = (function () { if (typeof window === "undefined" || !window.hasOwnProperty("navigator")) { return { @@ -155,8 +158,9 @@ Viva.BrowserInfo = (function () { version: match[2] || "0" }; }()); + /** - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ Viva.Graph.Utils = Viva.Graph.Utils || {}; @@ -177,6 +181,7 @@ Viva.Graph.Utils.indexOfElementInArray = function (element, array) { return -1; }; + Viva.Graph.Utils = Viva.Graph.Utils || {}; Viva.Graph.Utils.getDimension = function (container) { @@ -212,8 +217,9 @@ Viva.Graph.Utils.findElementPosition = function (obj) { } return [curleft, curtop]; -};/** - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com +}; +/** + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ Viva.Graph.Utils = Viva.Graph.Utils || {}; @@ -222,7 +228,7 @@ Viva.Graph.Utils = Viva.Graph.Utils || {}; // hard to understand. Refactor it. // TODO: This is really painful. Please don't use this class anymore, I will -// definitely depricate it or update its interface. +// definitely deprecate it or update its interface. /** * Allows to start/stop listen to element's events. An element can be arbitrary @@ -241,7 +247,7 @@ Viva.Graph.Utils.events = function (element) { * This behavior is based on Crockford's eventuality example, but with a minor changes: * - fire() method accepts parameters to pass to callbacks (instead of setting them in 'on' method) * - on() method is replaced with addEventListener(), to let objects be used as a DOM objects. - * - behavoir contract is simplified to "string as event name"/"function as callback" convention. + * - behavior contract is simplified to "string as event name"/"function as callback" convention. * - removeEventListener() method added to let unsubscribe from events. */ var eventuality = function (that) { @@ -327,10 +333,10 @@ Viva.Graph.Utils.events = function (element) { return { /** - * Registes callback to be called when element fires event with given event name. + * Registers callback to be called when element fires event with given event name. */ on : function (eventName, callback) { - if (element.addEventListener) {// W3C DOM and eventuality objecets. + if (element.addEventListener) {// W3C DOM and eventuality objects. element.addEventListener(eventName, callback, false); } else if (element.attachEvent) { // IE DOM element.attachEvent("on" + eventName, callback); @@ -361,8 +367,9 @@ Viva.Graph.Utils.events = function (element) { } }; }; + /** - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ Viva.Graph.Utils = Viva.Graph.Utils || {}; @@ -640,8 +647,9 @@ Viva.Graph.Utils.dragndrop = function (element) { } }; }; + /** - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ Viva.Input = Viva.Input || {}; @@ -682,6 +690,7 @@ Viva.Input.domInputManager = function (graph, graphics) { } }; }; + /** * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com */ @@ -760,7 +769,8 @@ Viva.Graph.Utils = Viva.Graph.Utils || {}; } }; }; -}());Viva.Graph.geom = function () { +}()); +Viva.Graph.geom = function () { return { // function from Graphics GEM to determine lines intersection: @@ -789,7 +799,7 @@ Viva.Graph.Utils = Viva.Graph.Utils || {}; */ if (r3 !== 0 && r4 !== 0 && ((r3 >= 0) === (r4 >= 4))) { - return null; //no itersection. + return null; //no intersection. } /* Compute a2, b2, c2 */ @@ -854,7 +864,7 @@ Viva.Graph.Utils = Viva.Graph.Utils || {}; dy = p.y - basePoint.y, sign = dx > 0 ? 1 : -1; - // We use squared dx, to avoid Sqrt opertion and improve performance. + // We use squared dx, to avoid Sqrt operation and improve performance. // To avoid sign loss during dx * dx operation we precompute its sign: return sign * dx * dx / (dx * dx + dy * dy); }, @@ -945,8 +955,10 @@ Viva.Graph.Utils = Viva.Graph.Utils || {}; return s; } }; -};/** - * Very generic rectangle. +}; + +/** + * Very generic rectangle. */ Viva.Graph.Rect = function (x1, y1, x2, y2) { this.x1 = x1 || 0; @@ -981,10 +993,11 @@ Viva.Graph.Link = function (fromId, toId, data, id) { this.data = data; this.id = id; }; + /** * @fileOverview Contains definition of the core graph object. * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ /** @@ -1003,7 +1016,7 @@ Viva.Graph.graph = function () { // hold all links related to that node. And general links // array is used to speed up all links enumeration. This is inefficient // in terms of memory, but simplifies coding. Furthermore, the graph structure - // is isolated from outter world, and can be changed to adjacency matrix later. + // is isolated from outer world, and can be changed to adjacency matrix later. var nodes = (typeof Object.create === 'function') ? Object.create(null) : {}, links = [], @@ -1012,7 +1025,7 @@ Viva.Graph.graph = function () { nodesCount = 0, suspendEvents = 0, - // Accumlates all changes made during graph updates. + // Accumulates all changes made during graph updates. // Each change element contains: // changeType - one of the strings: 'add', 'remove' or 'update'; // node - if change is related to node this property is set to changed graph's node; @@ -1024,7 +1037,7 @@ Viva.Graph.graph = function () { graph.fire('changed', changes); }, - // Enter, Exit Mofidication allows bulk graph updates without firing events. + // Enter, Exit modification allows bulk graph updates without firing events. enterModification = function () { suspendEvents += 1; }, @@ -1253,7 +1266,7 @@ Viva.Graph.graph = function () { // I.e. use array + 'for' iterator instead of dictionary + 'for .. in'? for (node in nodes) { if (callback(nodes[node])) { - return; // client doesn't want to proceed. return. + return; // client doesn't want to proceed. } } }, @@ -1273,7 +1286,7 @@ Viva.Graph.graph = function () { linkedNodeId; if (node && node.links && typeof callback === 'function') { - // Extraced orientation check out of the loop to increase performance + // Extracted orientation check out of the loop to increase performance if (oriented) { for (i = 0; i < node.links.length; ++i) { link = node.links[i]; @@ -1368,10 +1381,11 @@ Viva.Graph.graph = function () { return graphPart; }; + /** - * @fileOverview Contains collection of primitve operations under graph. + * @fileOverview Contains collection of primitive operations under graph. * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ Viva.Graph.operations = function () { @@ -1400,6 +1414,7 @@ Viva.Graph.operations = function () { } }; }; + Viva.Graph.Physics = Viva.Graph.Physics || {}; Viva.Graph.Physics.Vector = function (x, y) { @@ -1473,6 +1488,7 @@ Viva.Graph.Physics.QuadTreeNode = function () { this.x2 = 0; this.y2 = 0; }; + Viva.Graph.Physics = Viva.Graph.Physics || {}; /** @@ -1524,10 +1540,11 @@ Viva.Graph.Physics.eulerIntegrator = function () { } }; }; + /** * This is Barnes Hut simulation algorithm. Implementation * is adopted to non-recursive solution, since certain browsers - * handle recursion extremly bad. + * handle recursion extremely bad. * * http://www.cs.princeton.edu/courses/archive/fall03/cs126/assignments/barnes-hut.html */ @@ -1685,7 +1702,7 @@ Viva.Graph.Physics.nbodyForce = function (options) { // To achieve this we have to convert current leaf into internal node // and continue adding two nodes. var oldBody = node.body; - node.body = null; // internal nodes do not cary bodies + node.body = null; // internal nodes do not carry bodies node.isInternal = true; if (isSamePosition(oldBody.location, body.location)) { @@ -1749,13 +1766,13 @@ Viva.Graph.Physics.nbodyForce = function (options) { r = Math.sqrt(dx * dx + dy * dy); if (r === 0) { - // Poor man's protection agains zero distance. + // Poor man's protection against zero distance. dx = (random.nextDouble() - 0.5) / 50; dy = (random.nextDouble() - 0.5) / 50; r = Math.sqrt(dx * dx + dy * dy); } - // This is standard gravition force calculation but we divide + // This is standard gravitation force calculation but we divide // by r^3 to save two operations when normalizing force vector. v = gravity * body.mass * sourceBody.mass / (r * r * r); sourceBody.force.x = sourceBody.force.x + v * dx; @@ -1769,7 +1786,7 @@ Viva.Graph.Physics.nbodyForce = function (options) { r = Math.sqrt(dx * dx + dy * dy); if (r === 0) { - // Sorry about code duplucation. I don't want to create many functions + // Sorry about code duplication. I don't want to create many functions // right away. Just want to see performance first. dx = (random.nextDouble() - 0.5) / 50; dy = (random.nextDouble() - 0.5) / 50; @@ -1851,6 +1868,7 @@ Viva.Graph.Physics.nbodyForce = function (options) { } }; }; + Viva.Graph.Physics.dragForce = function (options) { if (!options) { options = {}; @@ -1876,6 +1894,7 @@ Viva.Graph.Physics.dragForce = function (options) { } }; }; + Viva.Graph.Physics.springForce = function (currentOptions) { currentOptions = Viva.lazyExtend(currentOptions, { length : 50, @@ -1920,12 +1939,13 @@ Viva.Graph.Physics.springForce = function (currentOptions) { } }; }; + Viva.Graph.Physics = Viva.Graph.Physics || {}; /** * Manages a simulation of physical forces acting on bodies. * To create a custom force simulator register forces of the system - * via addForce() method, choos appropriate integrator and register + * via addForce() method, choose appropriate integrator and register * bodies. * * // TODO: Show example. @@ -2082,6 +2102,7 @@ Viva.Graph.Physics.forceSimulator = function (forceIntegrator) { } }; }; + // I don't like to suppress this, but I'm afraid 'force_directed_body' // could already be used by someone. Don't want to break it now. /* jshint camelcase:false */ @@ -2112,7 +2133,7 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { gravity: -1.2, /** - * Theta coeffiecient from Barnes Hut simulation. Ranged between (0, 1). + * Theta coefficient from Barnes Hut simulation. Ranged between (0, 1). * The closer it's to 1 the more nodes algorithm will have to go through. * Setting it to one makes Barnes Hut simulation no different from * brute-force forces calculation (each node is considered). @@ -2126,7 +2147,7 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { dragCoeff: 0.02, /** - * Allows to transfor physical spring associated with a link. this allows clients + * Allows to transform physical spring associated with a link. This allows clients * to specify custom length for a link. * * @param {Viva.Graph.Link} link actual link for which transform is performed @@ -2489,9 +2510,9 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { }, /** - * Gets or sets current spring coeffiсient. + * Gets or sets current spring coefficient. * - * @param coeff new spring coeffiсient. + * @param coeff new spring coefficient. * if this parameter is empty then its old value returned. */ springCoeff: function(coeff) { @@ -2525,7 +2546,7 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { /** * Gets or sets current theta value in the nbody simulation. * - * @param t new theta coeffiсient. + * @param t new theta coefficient. * if this parameter is empty then its old value returned. */ theta: function(t) { @@ -2542,7 +2563,7 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { /** * Gets or sets current theta value in the nbody simulation. * - * @param dragCoeff new drag coeffiсient. + * @param dragCoeff new drag coefficient. * if this parameter is empty then its old value returned. */ drag: function(dragCoeff) { @@ -2557,6 +2578,7 @@ Viva.Graph.Layout.forceDirected = function(graph, settings) { } }; }; + Viva.Graph.Layout = Viva.Graph.Layout || {}; /** @@ -2739,10 +2761,11 @@ Viva.Graph.Layout.constant = function (graph, userSettings) { }; }; + /** * @fileOverview Defines a graph renderer that uses CSS based drawings. * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ Viva.Graph.View = Viva.Graph.View || {}; @@ -2779,14 +2802,14 @@ Viva.Graph.View = Viva.Graph.View || {}; * renderLinks : true, * * // Number of layout iterations to run before displaying the graph. The bigger you set this number - * // the closer to ideal position graph will apper first time. But be careful: for large graphs + * // the closer to ideal position graph will appear first time. But be careful: for large graphs * // it can freeze the browser. * prerender : 0 * } */ Viva.Graph.View.renderer = function (graph, settings) { // TODO: This class is getting hard to understand. Consider refactoring. - // TODO: I have a technical debt here: fix scaling/recentring! Currently it's total mess. + // TODO: I have a technical debt here: fix scaling/recentering! Currently it's a total mess. var FRAME_INTERVAL = 30; settings = settings || {}; @@ -3034,7 +3057,7 @@ Viva.Graph.View.renderer = function (graph, settings) { releaseGraphEvents = function () { if (graphEvents) { - // Interesting.. why is it not null? Anyway: + // Interesting.. Why is it not null? Anyway: graphEvents.stop('changed', onGraphChanged); graphEvents = null; } @@ -3198,6 +3221,7 @@ Viva.Graph.View.renderer = function (graph, settings) { } }; }; + Viva.Graph.serializer = function () { var checkJSON = function () { if (typeof JSON === 'undefined' || !JSON.stringify || !JSON.parse) { @@ -3297,19 +3321,20 @@ Viva.Graph.serializer = function () { } }; }; + /** - * @fileOverview Centrality calcuation algorithms. - * + * @fileOverview Centrality calculation algorithms. + * * @see http://en.wikipedia.org/wiki/Centrality * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ Viva.Graph.centrality = function () { var singleSourceShortestPath = function (graph, node, oriented) { // I'm using the same naming convention used in http://www.inf.uni-konstanz.de/algo/publications/b-fabc-01.pdf // sorry about cryptic names. - var P = {}, // predcessors lists. + var P = {}, // predecessors lists. S = [], sigma = {}, d = {}, @@ -3400,26 +3425,26 @@ Viva.Graph.centrality = function () { /** * Compute the shortest-path betweenness centrality for all nodes in a graph. - * - * Betweenness centrality of a node `n` is the sum of the fraction of all-pairs + * + * Betweenness centrality of a node `n` is the sum of the fraction of all-pairs * shortest paths that pass through `n`. Runtime O(n * v) for non-weighted graphs. * * @see http://en.wikipedia.org/wiki/Centrality#Betweenness_centrality - * - * @see A Faster Algorithm for Betweenness Centrality. + * + * @see A Faster Algorithm for Betweenness Centrality. * Ulrik Brandes, Journal of Mathematical Sociology 25(2):163-177, 2001. * http://www.inf.uni-konstanz.de/algo/publications/b-fabc-01.pdf - * - * @see Ulrik Brandes: On Variants of Shortest-Path Betweenness + * + * @see Ulrik Brandes: On Variants of Shortest-Path Betweenness * Centrality and their Generic Computation. * Social Networks 30(2):136-145, 2008. * http://www.inf.uni-konstanz.de/algo/publications/b-vspbc-08.pdf - * + * * @see Ulrik Brandes and Christian Pich: Centrality Estimation in Large Networks. * International Journal of Bifurcation and Chaos 17(7):2303-2318, 2007. * http://www.inf.uni-konstanz.de/algo/publications/bp-celn-06.pdf - * - * @param graph for which we are calculating betweenness centrality. Non-weighted graphs are only supported + * + * @param graph for which we are calculating betweenness centrality. Non-weighted graphs are only supported */ betweennessCentrality : function (graph) { var betweennes = {}, @@ -3438,9 +3463,9 @@ Viva.Graph.centrality = function () { /** * Calculates graph nodes degree centrality (in/out or both). - * + * * @see http://en.wikipedia.org/wiki/Centrality#Degree_centrality - * + * * @param graph for which we are calculating centrality. * @param kind optional parameter. Valid values are * 'in' - calculate in-degree centrality @@ -3506,29 +3531,33 @@ Viva.Graph.centrality = function () { return result; } }; -};/** +}; + +/** * @fileOverview Community structure detection algorithms - * + * * @see http://en.wikipedia.org/wiki/Community_structure * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ Viva.Graph.community = function () { return { /** * Implementation of Speaker-listener Label Propagation Algorithm (SLPA) of - * Jierui Xie and Boleslaw K. Szymanski. - * + * Jierui Xie and Boleslaw K. Szymanski. + * * @see http://arxiv.org/pdf/1109.5720v3.pdf - * @see https://sites.google.com/site/communitydetectionslpa/ + * @see https://sites.google.com/site/communitydetectionslpa/ */ slpa : function (graph, T, r) { var algorithm = Viva.Graph._community.slpaAlgorithm(graph, T, r); return algorithm.run(); } }; -};Viva.Graph._community = {}; +}; + +Viva.Graph._community = {}; /** * Implementation of Speaker-listener Label Propagation Algorithm (SLPA) of @@ -3660,7 +3689,7 @@ Viva.Graph._community.slpaAlgorithm = function (graph, T, r) { * A data structure which serves as node memory during SLPA execution. The main idea is to * simplify operations on memory such as * - add word to memory, - * - get random word from memory, with probablity proportional to word occurrence in the memory + * - get random word from memory, with probability proportional to word occurrence in the memory * - get the most popular word in memory * * TODO: currently this structure is extremely inefficient in terms of memory. I think it could be @@ -3690,9 +3719,9 @@ Viva.Graph._community.occuranceMap = function (random) { return result; } - // Not only number of occurances matters but order of keys also does. + // Not only number of occurrences matters but order of keys also does. // for ... in implementation in different browsers results in different - // order, and if we want to have same categories accross all browsers + // order, and if we want to have same categories across all browsers // we should order words by key names too: if (x < y) { return -1; } if (x > y) { return 1; } @@ -3726,7 +3755,7 @@ Viva.Graph._community.occuranceMap = function (random) { }, /** - * Gets number of occurances for a given word. If word is not present in the dictionary + * Gets number of occurrences for a given word. If word is not present in the dictionary * zero is returned. */ getWordCount : function (word) { @@ -3735,7 +3764,7 @@ Viva.Graph._community.occuranceMap = function (random) { /** * Gets the most popular word in the map. If multiple words are at the same position - * random word among them is choosen. + * random word among them is chosen. * */ getMostPopularFair : function () { @@ -3750,7 +3779,7 @@ Viva.Graph._community.occuranceMap = function (random) { for (i = 1; i < uniqueWords.length; ++i) { if (wordsCount[uniqueWords[i - 1]] !== wordsCount[uniqueWords[i]]) { - break; // other words are less popular... not interested. + break; // other words are less popular... Not interested. } else { maxCount += 1; } @@ -3766,7 +3795,7 @@ Viva.Graph._community.occuranceMap = function (random) { */ getRandomWord : function () { if (allWords.length === 0) { - throw 'The occurance map is empty. Cannot get empty word'; + throw 'The occurrence map is empty. Cannot get empty word'; } return allWords[random.next(allWords.length)]; @@ -3774,7 +3803,7 @@ Viva.Graph._community.occuranceMap = function (random) { /** * Enumerates all unique words in the map, and calls - * callback(word, occuranceCount) function on each word. Callback + * callback(word, occurrenceCount) function on each word. Callback * can return true value to stop enumeration. * * Note: enumeration is guaranteed in to run in decreasing order. @@ -3798,10 +3827,12 @@ Viva.Graph._community.occuranceMap = function (random) { } } }; -};/** +}; + +/** * @fileOverview Contains collection of graph generators. * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ Viva.Graph.generator = function () { @@ -3843,7 +3874,7 @@ Viva.Graph.generator = function () { */ completeBipartite : function (n, m) { if (!n || !m || n < 0 || m < 0) { - throw { message: "Graph dimensions are invalid. Number of nodes in each partition should be greate than 0" }; + throw { message: "Graph dimensions are invalid. Number of nodes in each partition should be greater than 0" }; } var g = Viva.Graph.graph(), @@ -4001,10 +4032,12 @@ Viva.Graph.generator = function () { } }; }; + /** * @fileOverview Defines a graph renderer that uses CSS based drawings. * * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * TODO: this should not be part of the library */ // The file tries to conform generic interface: /*jshint unused: false */ @@ -4013,10 +4046,10 @@ Viva.Graph.View = Viva.Graph.View || {}; /** * Performs css-based graph rendering. This module does not perform - * layout, but only visualizes nodes and edeges of the graph. + * layout, but only visualizes nodes and edges of the graph. * - * NOTE: Most likely I will remove this graphics engine due to superior svg support. - * In certain cases it doesn't work and require further imporvments: + * NOTE: Most likely I will remove this graphics engine due to superior SVG support. + * In certain cases it doesn't work and require further improvements: * * does not properly work for dragging. * * does not support scaling. * * does not support IE versions prior to IE9. @@ -4080,7 +4113,7 @@ Viva.Graph.View.cssGraphics = function () { // IE 6, 7 and 8 are screwed up when it comes to transforms; // I could not find justification for their choice of "floating" // matrix transform origin. The following ugly code was written - // out of complete dispair. + // out of complete despair. if (angleRad < 0) { angleRad = 2 * Math.PI + angleRad; } @@ -4160,7 +4193,7 @@ Viva.Graph.View.cssGraphics = function () { return { /** - * Sets the collback that creates node representation or creates a new node + * Sets the callback that creates node representation or creates a new node * presentation if builderCallbackOrNode is not a function. * * @param builderCallbackOrNode a callback function that accepts graph node @@ -4181,7 +4214,7 @@ Viva.Graph.View.cssGraphics = function () { }, /** - * Sets the collback that creates link representation or creates a new link + * Sets the callback that creates link representation or creates a new link * presentation if builderCallbackOrLink is not a function. * * @param builderCallbackOrLink a callback function that accepts graph link @@ -4324,8 +4357,9 @@ Viva.Graph.View.cssGraphics = function () { } }; }; + /** - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ /** @@ -4448,6 +4482,7 @@ Viva.Graph.svg = function (element) { return svgElement; }; + /** * @fileOverview Defines a graph renderer that uses SVG based drawings. * @@ -4458,7 +4493,7 @@ Viva.Graph.View = Viva.Graph.View || {}; /** * Performs svg-based graph rendering. This module does not perform - * layout, but only visualizes nodes and edeges of the graph. + * layout, but only visualizes nodes and edges of the graph. */ Viva.Graph.View.svgGraphics = function () { var svgContainer, @@ -4478,7 +4513,7 @@ Viva.Graph.View.svgGraphics = function () { }, nodePositionCallback = function (nodeUI, pos) { - // TODO: Remove magic 5. It should be halfo of the width or height of the node. + // TODO: Remove magic 5. It should be half of the width or height of the node. nodeUI.attr("x", pos.x - 5) .attr("y", pos.y - 5); }, @@ -4533,7 +4568,7 @@ Viva.Graph.View.svgGraphics = function () { */ node : function (builderCallback) { if (typeof builderCallback !== "function") { - return; // todo: throw? this is not compatible with old versions + return; // todo: throw? This is not compatible with old versions } nodeBuilder = builderCallback; @@ -4548,11 +4583,11 @@ Viva.Graph.View.svgGraphics = function () { * as a parameter and must return an element representing this link. * * @returns If builderCallback is a valid callback function, instance of this is returned; - * Otherwise undefined value is returend. + * Otherwise undefined value is returned. */ link : function (builderCallback) { if (typeof builderCallback !== "function") { - return; // todo: throw? this is not compatible with old versions + return; // todo: throw? This is not compatible with old versions } linkBuilder = builderCallback; @@ -4622,7 +4657,7 @@ Viva.Graph.View.svgGraphics = function () { p.x = scrollPoint.x; p.y = scrollPoint.y; - p = p.matrixTransform(svgContainer.getCTM().inverse()); // translate to svg coordinates + p = p.matrixTransform(svgContainer.getCTM().inverse()); // translate to SVG coordinates // Compute new scale matrix in current mouse position var k = svgRoot.createSVGMatrix().translate(p.x, p.y).scale(scaleFactor).translate(-p.x, -p.y), @@ -4653,7 +4688,7 @@ Viva.Graph.View.svgGraphics = function () { init : function (container) { container.appendChild(svgRoot); updateTransform(); - // Notify the world if someoen waited for update. TODO: should send an event + // Notify the world if someone waited for update. TODO: should send an event if (typeof initCallback === "function") { initCallback(svgRoot); } @@ -4776,7 +4811,7 @@ Viva.Graph.View.svgGraphics = function () { return svgRoot; }, /** - * Returns root svg element. + * Returns root SVG element. * * Note: This is internal method specific to this renderer */ @@ -4801,13 +4836,14 @@ Viva.Graph.View.svgGraphics = function () { return svgRoot; } }; + /** * @fileOverview I used this class to render links UI within * node. Lesser SVG elements is proven to improve performance * but I'm not happy with the code result here. Probably this class * will be removed from future versions. * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ Viva.Graph.View.svgNodeFactory = function (graph) { @@ -4852,7 +4888,7 @@ Viva.Graph.View.svgNodeFactory = function (graph) { }, /** - * Sets a callback function for custom nodes contnet. + * Sets a callback function for custom nodes content. * @param conentCreator(nodeUI, node) - callback function which returns a node content UI. * Image, for example. * @param sizeProvider(nodeUI) - a callback function which accepts nodeUI returned by @@ -4924,6 +4960,7 @@ Viva.Graph.View.svgNodeFactory = function (graph) { }; }; + /** * @fileOverview Utility functions for webgl rendering. * @@ -5024,11 +5061,12 @@ Viva.Graph.webgl = function (gl) { context : gl }; }; + /** * @fileOverview Defines a model objects to represents graph rendering * primitives in webglGraphics. * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ Viva.Graph.View.WebglUtils = function () { }; @@ -5086,7 +5124,7 @@ Viva.Graph.View.webglLine = function (color) { Viva.Graph.View.webglSquare = function (size, color) { return { /** - * Gets or sets size of the sqare side. + * Gets or sets size of the square side. */ size : typeof size === 'number' ? size : 10, @@ -5103,7 +5141,7 @@ Viva.Graph.View.webglSquare = function (size, color) { Viva.Graph.View.webglImage = function (size, src) { return { /** - * Gets texture index where current image is placed.s + * Gets texture index where current image is placed. */ _texture : 0, @@ -5118,17 +5156,19 @@ Viva.Graph.View.webglImage = function (size, src) { size : typeof size === 'number' ? size : 32, /** - * Source of the image. If image is comming not from your domain + * Source of the image. If image is coming not from your domain * certain origin restrictions applies. * See http://www.khronos.org/registry/webgl/specs/latest/#4.2 for more details. */ src : src }; -};/** +}; + +/** * @fileOverview Defines a naive form of nodes for webglGraphics class. * This form allows to change color of node. Shape of nodes is rectangular. * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ /** @@ -5266,12 +5306,13 @@ Viva.Graph.View.webglNodeProgram = function () { } }; }; + /** * @fileOverview Defines a naive form of links for webglGraphics class. * This form allows to change color of links. * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com - */ + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka + **/ /** * Defines UI for links in webgl renderer. @@ -5420,9 +5461,10 @@ Viva.Graph.View.webglLinkProgram = function () { } }; }; + /** * @fileOverview Defines an image nodes for webglGraphics class. - * Shape of nodes is sqare. + * Shape of nodes is square. * * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com */ @@ -5439,7 +5481,7 @@ Viva.Graph.View.Texture = function (size) { /** * My naive implementation of textures atlas. It allows clients to load - * multimple images into atlas and get canvas representing all of them. + * multiple images into atlas and get canvas representing all of them. * * @param tilesPerTexture - indicates how many images can be loaded to one * texture of the atlas. If number of loaded images exceeds this @@ -5544,7 +5586,7 @@ Viva.Graph.View.webglAtlas = function (tilesPerTexture) { }, /** - * Removes given url from colleciton of tiles in the atlas. + * Removes given url from collection of tiles in the atlas. */ remove : function (imgUrl) { var coordinates = loadedImages[imgUrl]; @@ -5838,17 +5880,19 @@ Viva.Graph.View.webglImageNodeProgram = function () { gl.drawArrays(gl.TRIANGLES, 0, nodesCount * 6); } }; -};/** +}; + +/** * @fileOverview Defines a graph renderer that uses WebGL based drawings. * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ Viva.Graph.View = Viva.Graph.View || {}; /** * Performs webgl-based graph rendering. This module does not perform - * layout, but only visualizes nodes and edeges of the graph. + * layout, but only visualizes nodes and edges of the graph. * * @param options - to customize graphics behavior. Currently supported parameter * enableBlending - true by default, allows to use transparency in node/links colors. @@ -5939,7 +5983,7 @@ Viva.Graph.View.webglGraphics = function (options) { }, /** - * Sets the collback that creates node representation. + * Sets the callback that creates node representation. * * @param builderCallback a callback function that accepts graph node * as a parameter and must return an element representing this node. @@ -5949,7 +5993,7 @@ Viva.Graph.View.webglGraphics = function (options) { */ node : function (builderCallback) { if (typeof builderCallback !== "function") { - return; // todo: throw? this is not compatible with old versions + return; // todo: throw? This is not compatible with old versions } nodeUIBuilder = builderCallback; @@ -5964,11 +6008,11 @@ Viva.Graph.View.webglGraphics = function (options) { * as a parameter and must return an element representing this link. * * @returns If builderCallback is a valid callback function, instance of this is returned; - * Otherwise undefined value is returend. + * Otherwise undefined value is returned. */ link : function (builderCallback) { if (typeof builderCallback !== "function") { - return; // todo: throw? this is not compatible with old versions + return; // todo: throw? This is not compatible with old versions } linkUIBuilder = builderCallback; @@ -6154,7 +6198,7 @@ Viva.Graph.View.webglGraphics = function (options) { var color = options.clearColorValue; gl.clearColor(color.r, color.g, color.b, color.a); // TODO: not the best way, really. Should come up with something better - // what if we need more updates inisde beginRender, like depth buffer? + // what if we need more updates inside beginRender, like depth buffer? this.beginRender = function () { gl.clear(gl.COLOR_BUFFER_BIT); }; @@ -6168,7 +6212,7 @@ Viva.Graph.View.webglGraphics = function (options) { updateTransformUniform(); - // Notify the world if someoen waited for update. TODO: should send an event + // Notify the world if someone waited for update. TODO: should send an event if (typeof initCallback === "function") { initCallback(graphicsRoot); } @@ -6243,7 +6287,7 @@ Viva.Graph.View.webglGraphics = function (options) { nodes[nodeIdToRemove] = lastNodeUI; lastNodeUI.id = nodeIdToRemove; - // Since concrete shaders may cache properties in the ui element + // Since concrete shaders may cache properties in the UI element // we are letting them to make this swap (e.g. image node shader // uses this approach to update node's offset in the atlas) nodeProgram.replaceProperties(nodeUI, lastNodeUI); @@ -6314,7 +6358,7 @@ Viva.Graph.View.webglGraphics = function (options) { // and let initialization logic take care about the rest. nodeProgram = newProgram; } else if (newProgram) { - throw "Not implemented. Cannot swap shader on the fly... yet."; + throw "Not implemented. Cannot swap shader on the fly... Yet."; // TODO: unload old shader and reinit. } }, @@ -6330,7 +6374,7 @@ Viva.Graph.View.webglGraphics = function (options) { // and let initialization logic take care about the rest. linkProgram = newProgram; } else if (newProgram) { - throw "Not implemented. Cannot swap shader on the fly... yet."; + throw "Not implemented. Cannot swap shader on the fly... Yet."; // TODO: unload old shader and reinit. } }, @@ -6376,6 +6420,7 @@ Viva.Graph.View.webglGraphics = function (options) { return graphics; }; + /** * Monitors graph-related mouse input in webgl graphics and notifies subscribers. * @@ -6593,8 +6638,9 @@ Viva.Graph.webglInputEvents = function (webglGraphics) { return webglGraphics.webglInputEvents; }; + /** - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ Viva.Input = Viva.Input || {}; diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index d2ea134..f11c7cb 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.5.8",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=4294967295&e+2127912214+(e<<12),e=4294967295&(3345072700^e^e>>>19),e=4294967295&e+374761393+(e<<5),e=4294967295&(e+3550635116^e<<9),e=4294967295&e+4251993797+(e<<3),e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||0>e.indexOf("compatible")&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;r.length>a;++a)o=r[a],i=o.method,i(n);return this},e.addEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";var r={method:n};return t.hasOwnProperty(e)?t[e].push(r):t[e]=[r],this},e.removeEventListener=function(e,n){if("function"!=typeof n)throw"Only functions allowed to be callbacks";if(t.hasOwnProperty(e)){var r,i=t[e];for(r=0;i.length>r;++r)if(i[r].callback===n){i.splice(r);break}}return this},e.removeAllListeners=function(){var e;for(e in t)t.hasOwnProperty(e)&&delete t[e]},e};return{on:function(t,n){return e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,n),this},stop:function(t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent&&e.detachEvent("on"+t,n)},extend:function(){return t(e)}}},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.dragndrop=function(e){var t,n,r,i,o,a,u,s=Viva.Graph.Utils.events(window.document),f=Viva.Graph.Utils.events(e),c=Viva.Graph.Utils.findElementPosition,d=0,l=0,h=!1,v=0,p=function(e){var t=0,n=0;return e=e||window.event,e.pageX||e.pageY?(t=e.pageX,n=e.pageY):(e.clientX||e.clientY)&&(t=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,n=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[t,n]},m=function(e,t,r){n&&n(e,{x:t-d,y:r-l}),d=t,l=r},g=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return g(e),!1},w=function(e){e=e||window.event,m(e,e.clientX,e.clientY)},V=function(e){if(e=e||window.event,h)return g(e),!1;var n=1===e.button&&null!==window.event||0===e.button;return n?(d=e.clientX,l=e.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),s.on("mousemove",w),s.on("mouseup",b),g(e),o=window.document.onselectstart,a=window.document.ondragstart,window.document.onselectstart=x,u.ondragstart=x,!1):void 0},b=function(e){e=e||window.event,s.stop("mousemove",w),s.stop("mouseup",b),window.document.onselectstart=o,u.ondragstart=a,u=null,r&&r(e)},N=function(t){if("function"==typeof i){t=t||window.event,t.preventDefault&&t.preventDefault(),t.returnValue=!1;var n,r=p(t),o=c(e),a={x:r[0]-o[0],y:r[1]-o[1]};n=t.wheelDelta?t.wheelDelta/360:t.detail/-9,i(t,n,a)}},P=function(t){!i&&t?"webkit"===Viva.BrowserInfo.browser?e.addEventListener("mousewheel",N,!1):e.addEventListener("DOMMouseScroll",N,!1):i&&!t&&("webkit"===Viva.BrowserInfo.browser?e.removeEventListener("mousewheel",N,!1):e.removeEventListener("DOMMouseScroll",N,!1)),i=t},E=function(e,t){return(e.clientX-t.clientX)*(e.clientX-t.clientX)+(e.clientY-t.clientY)*(e.clientY-t.clientY)},G=function(e){if(1===e.touches.length){g(e);var t=e.touches[0];m(e,t.clientX,t.clientY)}else if(2===e.touches.length){var n=E(e.touches[0],e.touches[1]),r=0;v>n?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])),void 0)};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return P(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),P(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;r.length>e&&!t.requestAnimationFrame;++e){var i=r[e];t.requestAnimationFrame=t[i+"RequestAnimationFrame"],t.cancelAnimationFrame=t[i+"CancelAnimationFrame"]||t[i+"CancelRequestAnimationFrame"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(e){var r=(new Date).getTime(),i=Math.max(0,16-(r-n)),o=t.setTimeout(function(){e(r+i)},i);return n=r+i,o}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(e){t.clearTimeout(e)}),Viva.Graph.Utils.timer=function(e){var n,r=function(){t.cancelAnimationFrame(n),n=0},i=function(){n=t.requestAnimationFrame(i),e()||r()};return i(),{stop:r,restart:function(){n||i()}}}}(),Viva.Graph.geom=function(){return{intersect:function(e,t,n,r,i,o,a,u){var s,f,c,d,l,h,v,p,m,g,y,x,w,V={x:0,y:0};return s=r-t,c=e-n,l=n*t-e*r,m=s*i+c*o+l,g=s*a+c*u+l,0!==m&&0!==g&&m>=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;o.length>r;++r){a=o[r];var d=i(a);d===u?(s=a.x-e.x,f=a.y-e.y,n=s*s+f*f,c>n?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return 0>(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)};if(3>e.length)return e;var r,i=0;for(r=0;e.length>r;++r)e[r].ya.length)return a;var u=[];u.push(o),u.push(a[0]),u.push(a[1]);var s=u.length;for(r=2;a.length>r;++r){for(;!n(u[s-2],u[s-1],a[r]);)u.pop(),s-=1;u.push(a[r]),s+=1}return u}}},Viva.Graph.Rect=function(e,t,n,r){this.x1=e||0,this.y1=t||0,this.x2=n||0,this.y2=r||0},Viva.Graph.Point2d=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Node=function(e){this.id=e,this.links=[],this.data=null},Viva.Graph.Link=function(e,t,n,r){this.fromId=e,this.toId=t,this.data=n,this.id=r},Viva.Graph.graph=function(){var e="function"==typeof Object.create?Object.create(null):{},t=[],n={},r=0,i=0,o=[],a=function(e){e.fire("changed",o)},u=function(){i+=1},s=function(e){i-=1,0===i&&o.length>0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if(t===void 0)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=""+e+"👉 "+(""+r),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;u.links.length>i;++i)o=u.links[i],o.fromId===t&&n(e[o.toId],o);else for(i=0;u.links.length>i;++i)o=u.links[i],a=o.fromId===t?o.toId:o.fromId,n(e[a],o)},forEachLink:function(e){var n,r;if("function"==typeof e)for(n=0,r=t.length;r>n;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;r.links.length>n;++n){var i=r.links[n];if(i.fromId===e&&i.toId===t)return i}return null}};return Viva.Graph.Utils.events(d).extend(),d},Viva.Graph.operations=function(){return{density:function(e,t){var n=e.getNodesCount();return 0===n?0/0:t?e.getLinksCount()/(n*(n-1)):2*e.getLinksCount()/(n*(n-1))}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.Vector=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Vector.prototype={multiply:function(e){return new Viva.Graph.Physics.Vector(this.x*e,this.y*e)}},Viva.Graph.Physics.Point=function(e,t){this.x=e||0,this.y=t||0},Viva.Graph.Physics.Point.prototype={add:function(e){return new Viva.Graph.Physics.Point(this.x+e.x,this.y+e.y)}},Viva.Graph.Physics.Body=function(){this.mass=1,this.force=new Viva.Graph.Physics.Vector,this.velocity=new Viva.Graph.Physics.Vector,this.location=new Viva.Graph.Physics.Point,this.prevLocation=new Viva.Graph.Physics.Point},Viva.Graph.Physics.Body.prototype={loc:function(e){return e?(this.location.x=e.x,this.location.y=e.y,this):this.location},vel:function(e){return e?(this.velocity.x=e.x,this.velocity.y=e.y,this):this.velocity}},Viva.Graph.Physics.Spring=function(e,t,n,r,i){this.body1=e,this.body2=t,this.length=n,this.coeff=r,this.weight=i},Viva.Graph.Physics.QuadTreeNode=function(){this.centerOfMass=new Viva.Graph.Physics.Point,this.children=[],this.body=null,this.hasChildren=!1,this.x1=0,this.y1=0,this.x2=0,this.y2=0},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.eulerIntegrator=function(){return{integrate:function(e,t){var n,r=e.speedLimit,i=0,o=0,a=0,u=0,s=e.bodies.length;for(n=0;s>n;++n){var f=e.bodies[n],c=t/f.mass;f.velocity.x+=c*f.force.x,f.velocity.y+=c*f.force.y;var d=f.velocity.x,l=f.velocity.y,h=Math.sqrt(d*d+l*l);h>r&&(f.velocity.x=r*d/h,f.velocity.y=r*l/h),o=t*f.velocity.x,u=t*f.velocity.y,f.location.x+=o,f.location.y+=u,i+=Math.abs(o),a+=Math.abs(u)}return(i+a)/s}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(1e-8>n.right-n.left)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),a>(v.right-v.left)/s?(t=r*v.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(v.quads[0]&&(f[h]=v.quads[0],c+=1,h+=1),v.quads[1]&&(f[h]=v.quads[1],c+=1,h+=1),v.quads[2]&&(f[h]=v.quads[2],c+=1,h+=1),v.quads[3]&&(f[h]=v.quads[3],c+=1,h+=1)))}},m=function(e){var t,n=Number.MAX_VALUE,r=Number.MAX_VALUE,i=Number.MIN_VALUE,o=Number.MIN_VALUE,a=e.bodies,u=a.length;for(t=u;t--;){var s=a[t].location.x,f=a[t].location.y;n>s&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=0>n.length?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||0>n.coeff?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};r="number"==typeof r?r:1;var o=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,r);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02,springTransform:function(){},timeStep:20,stableThreshold:.009});var n=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),r=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),i=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),o=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),a=new Viva.Graph.Rect,u=Viva.random("ted.com",103,114,101,97,116),s={},f=function(e){if(e.position)return e.position;var n=(a.x1+a.x2)/2,r=(a.y1+a.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],f=o.fromId!==e.id?s[o.fromId]:s[o.toId];f&&f.location&&(n=f.location.x,r=f.location.y)}return{x:n+u.next(i)-i/2,y:r+u.next(i)-i/2}},c=function(e){return s[e]},d=function(e){s[e]=null,delete s[e]},l={},h=function(t){var n=c(t);n.mass=1+e.getLinks(t).length/3},v=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},p=function(e){return e.isPinned},m=function(t){var r=c(t);if(!r){var i=e.getNode(t);if(!i)return;r=new Viva.Graph.Physics.Body,s[t]=r;var o=f(i);r.loc(o),h(t),v(i)&&(r.isPinned=!0),n.addBody(r)}},g=function(e){m(e.id)},y=function(t){var r=c(t.id);r&&(d(t.id),n.removeBody(r),0===e.getNodesCount()&&(a.x1=a.y1=0,a.x2=a.y2=0))},x=function(e){h(e.fromId),h(e.toId);var r=c(e.fromId),i=c(e.toId),o=n.addSpring(r,i,-1,e.weight);t.springTransform(e,o),l[e.id]=o},w=function(t){var r=l[t.id];if(r){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&h(i.id),o&&h(o.id),delete l[t.id],n.removeSpring(r)}},V=function(e){for(var t=0;e.length>t;++t){var n=e[t];"add"===n.changeType?(n.node&&m(n.node.id),n.link&&x(n.link)):"remove"===n.changeType&&(n.node&&y(n.node),n.link&&w(n.link))}},b=function(){e.forEachNode(g),e.forEachLink(x),e.addEventListener("changed",V)},N=function(){var t=Number.MAX_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE,i=Number.MIN_VALUE;if(0!==e.getNodesCount()){for(var o in s)if(s.hasOwnProperty(o)){var u=s[o];p(u)?(u.location.x=u.prevLocation.x,u.location.y=u.prevLocation.y):(u.prevLocation.x=u.location.x,u.prevLocation.y=u.location.y),t>u.location.x&&(t=u.location.x),u.location.x>r&&(r=u.location.x),n>u.location.y&&(n=u.location.y),u.location.y>i&&(i=u.location.y)}a.x1=t,a.x2=r,a.y1=n,a.y2=i}};return n.setSpringForce(i),n.setNbodyForce(r),n.setDragForce(o),b(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=n.run(t.timeStep);return N(),t.stableThreshold>e},isNodePinned:function(e){var t=c(e.id);return t?p(t):void 0},pinNode:function(e,t){var n=c(e.id);n.isPinned=!!t},getNodePosition:function(e){var t=c(e);return t||(m(e),t=c(e)),t&&t.location},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=c(e.id);r&&(r.prevLocation.x=r.location.x=t,r.prevLocation.y=r.location.y=n)},getGraphRect:function(){return a},dispose:function(){e.removeEventListener("change",V)},springLength:function(e){return 1===arguments.length?(i.options({length:e}),this):i.options().length},springCoeff:function(e){return 1===arguments.length?(i.options({coeff:e}),this):i.options().coeff},gravity:function(e){return 1===arguments.length?(r.options({gravity:e}),this):r.options().gravity},theta:function(e){return 1===arguments.length?(r.options({theta:e}),this):r.options().theta},drag:function(e){return 1===arguments.length?(o.options({coeff:e}),this):o.options().coeff}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.constant=function(e,t){t=Viva.lazyExtend(t,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var n=Viva.random(t.seed),r=new Viva.Graph.Rect(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),i=function(){return new Viva.Graph.Point2d(n.next(t.maxX),n.next(t.maxY))},o=function(e,t){e.xt.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a="function"==typeof Object.create?Object.create(null):{},u=function(e){e&&(a[e.id]=i(e),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;e.length>t;++t){var n=e[t];n.node&&("add"===n.changeType?u(n.node):delete a[n.node.id])}};return e.addEventListener("changed",f),{run:function(){this.step()},step:function(){return s(),!0},getGraphRect:function(){return r},dispose:function(){e.removeEventListener("change",f)},isNodePinned:function(){return!0},pinNode:function(){},getNodePosition:function(t){var n=a[t];return n||u(e.getNode(t)),n},getLinkPosition:function(e){var t=this.getNodePosition(e.fromId),n=this.getNodePosition(e.toId);return{from:t,to:n}},setNodePosition:function(e,t,n){var r=a[e.id];r&&(r.x=t,r.y=n)},placeNode:function(e){return"function"==typeof e?(i=e,s(),this):i(e)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.renderer=function(e,t){var n=30;t=t||{};var r,i,o,a,u=t.layout,s=t.graphics,f=t.container,c=void 0!==t.interactive?t.interactive:!0,d=!1,l=!0,h=0,v=0,p=!1,m=!1,g=!1,y={x:0,y:0},x={offsetX:0,offsetY:0,scale:1},w=function(){f=f||window.document.body,u=u||Viva.Graph.Layout.forceDirected(e),s=s||Viva.Graph.View.svgGraphics(e,{container:f}),t.hasOwnProperty("renderLinks")||(t.renderLinks=!0),t.prerender=t.prerender||0,r=(s.inputManager||Viva.Input.domInputManager)(e,s)},V=Viva.Graph.Utils.events(window),b=Viva.Graph.Utils.events({}).extend(),N=function(){s.beginRender(),t.renderLinks&&s.renderLinks(),s.renderNodes(),s.endRender()},P=function(){return p=u.step()&&!m,N(),!p},E=function(e){return i?(v+=e,void 0):(e?(v+=e,i=Viva.Graph.Utils.timer(function(){return P()},n)):(h=0,v=0,i=Viva.Graph.Utils.timer(P,n)),void 0)},G=function(){g||(p=!1,i.restart())},L=function(){var e;if("number"==typeof t.prerender&&t.prerender>0)for(e=0;t.prerender>e;e+=1)u.step()},_=function(){var e=u.getGraphRect(),t=Viva.Graph.Utils.getDimension(f);y.x=y.y=0,x.offsetX=t.width/2-(e.x2+e.x1)/2,x.offsetY=t.height/2-(e.y2+e.y1)/2,s.graphCenterChanged(x.offsetX,x.offsetY),l=!1},A=function(e){var t=u.getNodePosition(e.id);s.addNode(e,t)},I=function(e){s.releaseNode(e)},k=function(e){var t=u.getLinkPosition(e);s.addLink(e,t)},T=function(e){s.releaseLink(e)},C=function(e){var t=!1,n="string"==typeof c&&-1!==c.indexOf("node")||c;n&&r.bindDragNDrop(e,{onStart:function(){t=u.isNodePinned(e),u.pinNode(e,!0),m=!0,G()},onDrag:function(t,n){var r=u.getNodePosition(e.id);u.setNodePosition(e,r.x+n.x/x.scale,r.y+n.y/x.scale),m=!0,N()},onStop:function(){u.pinNode(e,t),m=!1}})},S=function(e){r.bindDragNDrop(e,null)},M=function(){s.init(f),e.forEachNode(A),t.renderLinks&&e.forEachLink(k)},U=function(){s.release(f)},D=function(t){var n=t.node;"add"===t.changeType?(A(n),C(n),l&&_()):"remove"===t.changeType?(S(n),I(n),0===e.getNodesCount()&&(l=!0)):"update"===t.changeType&&(S(n),I(n),A(n),C(n))},R=function(e){var n=e.link;if("add"===e.changeType)t.renderLinks&&k(n);else if("remove"===e.changeType)t.renderLinks&&T(n);else if("update"===e.changeType)throw"Update type is not implemented. TODO: Implement me!"},O=function(e){var t,n;for(t=0;e.length>t;t+=1)n=e[t],n.node?D(n):n.link&&R(n);G()},F=function(){_(),P()},z=function(){a&&(a.release(),a=null)},B=function(){o&&(o.stop("changed",O),o=null)},Y=function(e,t){if(!t){var n=Viva.Graph.Utils.getDimension(f);t={x:n.width/2,y:n.height/2}}var r=Math.pow(1.4,e?-.2:.2);return x.scale=s.scale(r,t),N(),b.fire("scale",x.scale),x.scale},X=function(){V.on("resize",F),z();var t="string"==typeof c&&-1!==c.indexOf("drag")||c;t&&(a=Viva.Graph.Utils.dragndrop(f),a.onDrag(function(e,t){y.x+=t.x,y.y+=t.y,s.translateRel(t.x,t.y),N()}));var n="string"==typeof c&&-1!==c.indexOf("scroll")||c;n&&a.onScroll(function(e,t,n){Y(0>t,n)}),e.forEachNode(C),B(),o=Viva.Graph.Utils.events(e),o.on("changed",O)},q=function(){d=!1,B(),z(),V.stop("resize",F),b.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&T(e)}),e.forEachNode(function(e){S(e),I(e)}),u.dispose(),U()};return{run:function(e){return d||(w(),L(),_(),M(),X(),d=!0),E(e),this},reset:function(){s.resetScale(),_(),x.scale=1},pause:function(){g=!0,i.stop()},resume:function(){g=!1,i.restart()},rerender:function(){return N(),this},zoomOut:function(){return Y(!0)},zoomIn:function(){return Y(!1)},moveTo:function(e,t){s.graphCenterChanged(x.offsetX-e*x.scale,x.offsetY-t*x.scale),N()},getGraphics:function(){return s},dispose:function(){q()},on:function(e,t){return b.addEventListener(e,t),this},off:function(e,t){return b.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;u.nodes.length>a;++a){var f=n(u.nodes[a]);if(!f.hasOwnProperty("id"))throw"Graph node format is invalid. Node.id is missing";s.addNode(f.id,f.data)}for(a=0;u.links.length>a;++a){var c=o(u.links[a]);if(!c.hasOwnProperty("fromId")||!c.hasOwnProperty("toId"))throw"Graph link format is invalid. Both fromId and toId are required";s.addLink(c.fromId,c.toId,c.data)}return s}}},Viva.Graph.centrality=function(){var e=function(e,t,n){var r,i,o,a={},u=[],s={},f={},c=[t.id],d=function(e){f.hasOwnProperty(e.id)||(c.push(e.id),f[e.id]=i+1),f[e.id]===i+1&&(s[e.id]+=o,a[e.id].push(r))};for(e.forEachNode(function(e){a[e.id]=[],s[e.id]=0}),f[t.id]=0,s[t.id]=1;c.length;)r=c.shift(),i=f[r],o=s[r],u.push(r),e.forEachLinkedNode(r,d,n);return{S:u,P:a,sigma:s}},t=function(e,t,n){var r,i,o,a,u,s={},f=t.S;for(r=0;f.length>r;r+=1)s[f[r]]=0;for(;f.length;){for(i=f.pop(),o=(1+s[i])/t.sigma[i],a=t.P[i],r=0;a.length>r;r+=1)u=a[r],s[u]+=t.sigma[u]*o;i!==n&&(e[i]+=s[i])}},n=function(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({key:t,value:e[t]});return n.sort(function(e,t){return t.value-e.value})};return{betweennessCentrality:function(r){var i,o={};return r.forEachNode(function(e){o[e.id]=0}),r.forEachNode(function(n){i=e(r,n),t(o,i,n)}),n(o)},degreeCentrality:function(e,t){var n,r,i=[],o=[];if(t=(t||"both").toLowerCase(),"in"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].toId===t?1:0;return r};else if("out"===t)n=function(e,t){var n,r=0;for(n=0;e.length>n;n+=1)r+=e[n].fromId===t?1:0;return r};else{if("both"!==t)throw"Expected centrality degree kind is: in, out or both";n=function(e){return e.length}}e.forEachNode(function(t){var r=e.getLinks(t.id),o=n(r,t.id);i.hasOwnProperty(o)?i[o].push(t.id):i[o]=[t.id]});for(r in i)if(i.hasOwnProperty(r)){var a,u=i[r];if(u)for(a=0;u.length>a;++a)o.unshift({key:u[a],value:parseInt(r,10)})}return o}}},Viva.Graph.community=function(){return{slpa:function(e,t,n){var r=Viva.Graph._community.slpaAlgorithm(e,t,n);return r.run()}}},Viva.Graph._community={},Viva.Graph._community.slpaAlgorithm=function(e,t,n){t=t||100,n=n||.3;var r=Viva.random(1331782216905),i=Viva.random("Greeting goes to you, ","dear reader"),o=function(e,n){var r=[];return e.forEachUniqueWord(function(e,i){return i>n?(r.push({name:e,probability:i/t}),void 0):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;a.length>i;++i){var u=a[i].name;r.hasOwnProperty(u)?r[u].push(e.id):r[u]=[e.id]}e.communities=a,e.slpa=null,delete e.slpa}),r};return{run:function(){var t=a(e);return u(e,t),s(e)}}},Viva.Graph._community.occuranceMap=function(e){e=e||Viva.random();var t={},n=[],r=!1,i=[],o=function(){var e;i.length=0;for(e in t)t.hasOwnProperty(e)&&i.push(e);i.sort(function(e,n){var r=t[n]-t[e];return r?r:n>e?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e+="",t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;i.length>r&&t[i[r-1]]===t[i[r]];++r)o+=1;return o+=1,i[e.next(o)]},getRandomWord:function(){if(0===n.length)throw"The occurance map is empty. Cannot get empty word";return n[e.next(n.length)]},forEachUniqueWord:function(e){if("function"!=typeof e)throw"Function callback is expected to enumerate all words";var n;for(a(),n=0;i.length>n;++n){var r=i[n],o=t[r],u=e(r,o);if(u)break}}}},Viva.Graph.generator=function(){return{complete:function(e){if(!e||1>e)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greate than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r); -return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),Math.PI/2>r?(e.style.left=t+"px",e.style.top=n+"px"):Math.PI>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n):Math.PI+Math.PI/2>r?(e.style.left=t-e.clientWidth*Math.cos(Math.PI-r),e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)):(e.style.left=t,e.style.top=n+e.clientWidth*Math.sin(Math.PI-r)),e.style.filter='progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand",M11='+i+", M12="+-o+","+"M21="+o+", M22="+i+");"}:a?function(e,t,n,r){e.style.left=t+"px",e.style.top=n+"px",e.style[a]="rotate("+r+"rad)",e.style[a+"Origin"]="left"}:function(){}}(),s=function(){var e=window.document.createElement("div");return e.setAttribute("class","node"),e},f=function(e,t){e.style.left=t.x-5+"px",e.style.top=t.y-5+"px"},c=function(e,t,n){var r=t.x-n.x,i=t.y-n.y,o=Math.sqrt(r*r+i*i);e.style.height="1px",e.style.width=o+"px",u(e,n.x,n.y,Math.atan2(i,r))},d=function(){var e=window.document.createElement("div");return e.setAttribute("class","link"),e},l=function(){if(e){if(!a||a===r)throw"Not implemented. TODO: Implement OLD_IE Filter based transform";var u="matrix("+i+", 0, 0,"+o+","+t+","+n+")";e.style[a]=u}};return{node:function(e){return e&&"function"!=typeof e?s(e):(s=e,this)},link:function(e){return e&&"function"!=typeof e?d(e):(d=e,this)},inputManager:Viva.Input.domInputManager,graphCenterChanged:function(e,r){t=e,n=r,l()},translateRel:function(e,r){t+=e,n+=r,l()},scale:function(){return 1},resetScale:function(){return this},beginRender:function(){},endRender:function(){},placeNode:function(e){return f=e,this},placeLink:function(e){return c=e,this},init:function(t){e=t,l()},initLink:function(t){e.childElementCount>0?e.insertBefore(t,e.firstChild):e.appendChild(t)},releaseLink:function(t){e.removeChild(t)},initNode:function(t){e.appendChild(t)},releaseNode:function(t){e.removeChild(t)},updateNodePosition:function(e,t){f(e,t)},updateLinkPosition:function(e,t,n){c(e,t,n)}}},Viva.Graph.svg=function(e){var t="http://www.w3.org/2000/svg",n="http://www.w3.org/1999/xlink",r=e;return"string"==typeof e&&(r=window.document.createElementNS(t,e)),r.vivagraphAugmented?r:(r.vivagraphAugmented=!0,r.attr=function(e,t){return 2===arguments.length?(null!==t?r.setAttributeNS(null,e,t):r.removeAttributeNS(null,e),r):r.getAttributeNS(null,e)},r.append=function(e){var t=Viva.Graph.svg(e);return r.appendChild(t),t},r.text=function(e){return e!==void 0?(r.textContent=e,r):r.textContent},r.link=function(e){return arguments.length?(r.setAttributeNS(n,"xlink:href",e),r):r.getAttributeNS(n,"xlink:href")},r.children=function(e){var t,n,i=[],o=r.childNodes.length;if(void 0===e&&r.hasChildNodes())for(t=0;o>t;t++)i.push(Viva.Graph.svg(r.childNodes[t]));else if("string"==typeof e){var a="."===e[0],u="#"===e[0],s=!a&&!u;for(t=0;o>t;t++){var f=r.childNodes[t];if(1===f.nodeType){var c=f.attr("class"),d=f.attr("id"),l=f.nodeName;if(a&&c){for(c=c.replace(/\s+/g," ").split(" "),n=0;c.length>n;n++)if(a&&c[n]===e.substr(1)){i.push(Viva.Graph.svg(f));break}}else{if(u&&d===e.substr(1)){i.push(Viva.Graph.svg(f));break}s&&l===e&&i.push(Viva.Graph.svg(f))}i=i.concat(Viva.Graph.svg(f).children(e))}}if(u&&1===i.length)return i[0]}return i},r)},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.svgGraphics=function(){function e(){var e=Viva.Graph.svg("svg");return t=Viva.Graph.svg("g").attr("buffered-rendering","dynamic"),e.appendChild(t),e}var t,n,r,i,o,a=1,u={},s={},f=function(){return Viva.Graph.svg("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},c=function(e,t){e.attr("x",t.x-5).attr("y",t.y-5)},d=function(){return Viva.Graph.svg("line").attr("stroke","#999")},l=function(e,t,n){e.attr("x1",t.x).attr("y1",t.y).attr("x2",n.x).attr("y2",n.y)},h=function(e){e.fire("rescaled")},v={x:0,y:0},p={x:0,y:0},m={x:0,y:0},g=function(){if(t){var e="matrix("+a+", 0, 0,"+a+","+r+","+i+")";t.attr("transform",e)}};n=e();var y={getNodeUI:function(e){return u[e]},getLinkUI:function(e){return s[e]},node:function(e){return"function"==typeof e?(f=e,this):void 0},link:function(e){return"function"==typeof e?(d=e,this):void 0},placeNode:function(e){return c=e,this},placeLink:function(e){return l=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,t){r=e,i=t,g()},inputManager:Viva.Input.domInputManager,translateRel:function(e,r){var i=n.createSVGPoint(),o=t.getCTM(),a=n.createSVGPoint().matrixTransform(o.inverse());i.x=e,i.y=r,i=i.matrixTransform(o.inverse()),i.x=(i.x-a.x)*o.a,i.y=(i.y-a.y)*o.d,o.e+=i.x,o.f+=i.y;var u="matrix("+o.a+", 0, 0,"+o.d+","+o.e+","+o.f+")";t.attr("transform",u)},scale:function(e,o){var u=n.createSVGPoint();u.x=o.x,u.y=o.y,u=u.matrixTransform(t.getCTM().inverse());var s=n.createSVGMatrix().translate(u.x,u.y).scale(e).translate(-u.x,-u.y),f=t.getCTM().multiply(s);a=f.a,r=f.e,i=f.f;var c="matrix("+f.a+", 0, 0,"+f.d+","+f.e+","+f.f+")";return t.attr("transform",c),h(this),a},resetScale:function(){a=1;var e="matrix(1, 0, 0, 1, 0, 0)";return t.attr("transform",e),h(this),this},init:function(e){e.appendChild(n),g(),"function"==typeof o&&o(n)},release:function(e){n&&e&&e.removeChild(n)},addLink:function(e,n){var r=d(e);if(r)return r.position=n,r.link=e,s[e.id]=r,t.childElementCount>0?t.insertBefore(r,t.firstChild):t.appendChild(r),r},releaseLink:function(e){var n=s[e.id];n&&(t.removeChild(n),delete s[e.id])},addNode:function(e,n){var r=f(e);if(r)return r.position=n,r.node=e,u[e.id]=r,t.appendChild(r),r},releaseNode:function(e){var n=u[e.id];n&&(t.removeChild(n),delete u[e.id])},renderNodes:function(){for(var e in u)if(u.hasOwnProperty(e)){var t=u[e];v.x=t.position.x,v.y=t.position.y,c(t,v,t.node)}},renderLinks:function(){for(var e in s)if(s.hasOwnProperty(e)){var t=s[e];p.x=t.position.from.x,p.y=t.position.from.y,m.x=t.position.to.x,m.y=t.position.to.y,l(t,p,m,t.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):o=e),n},getSvgRoot:function(){return n}};return Viva.Graph.Utils.events(y).extend(),y},Viva.Graph.View.svgNodeFactory=function(e){var t="#999",n=Viva.Graph.geom(),r=function(e){e.size={w:10,h:10},e.append("rect").attr("width",e.size.w).attr("height",e.size.h).attr("stroke","orange").attr("fill","orange")},i=function(e){return e.size};return{node:function(e){var t=Viva.Graph.svg("g");return r(t,e),t.nodeId=e.id,t},link:function(n){var r=e.getNode(n.fromId),i=r&&r.ui;if(i&&!i.linksContainer){var o=Viva.Graph.svg("path").attr("stroke",t);return i.linksContainer=o,o}return null},customContent:function(e,t){if("function"!=typeof e||"function"!=typeof t)throw"Two functions expected: contentCreator(nodeUI, node) and size(nodeUI)";r=e,i=t},placeNode:function(t,r){var o="",a=i(t);e.forEachLinkedNode(t.nodeId,function(e,u){if(e.position&&e.ui&&e.ui!==t&&u.fromId===t.nodeId){var s=i(e.ui),f=e.position,c=n.intersectRect(r.x-a.w/2,r.y-a.h/2,r.x+a.w/2,r.y+a.h/2,r.x,r.y,f.x,f.y)||r,d=n.intersectRect(f.x-s.w/2,f.y-s.h/2,f.x+s.w/2,f.y+s.h/2,f.x,f.y,r.x,r.y)||f;o+="M"+Math.round(c.x)+" "+Math.round(c.y)+"L"+Math.round(d.x)+" "+Math.round(d.y)}}),t.attr("transform","translate("+(r.x-a.w/2)+", "+(r.y-a.h/2)+")"),""!==o&&t.linksContainer&&t.linksContainer.attr("d",o)}}},Viva.Graph.webgl=function(e){var t=function(t,n){var r=e.createShader(n);if(e.shaderSource(r,t),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(r);throw window.alert(i),i}return r};return{createProgram:function(n,r){var i=e.createProgram(),o=t(n,e.VERTEX_SHADER),a=t(r,e.FRAGMENT_SHADER);if(e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS)){var u=e.getShaderInfoLog(i);throw window.alert(u),u}return i},extendArray:function(e,t,n){if((t+1)*n>e.length){var r=new Float32Array(2*e.length*n);return r.set(e),r}return e},copyArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i)e[t+i]=e[n+i]},swapArrayPart:function(e,t,n,r){var i;for(i=0;r>i;++i){var o=e[t+i];e[t+i]=e[n+i],e[n+i]=o}},getLocations:function(t,n){var r,i={};for(r=0;n.length>r;++r){var o=n[r],a=-1;if(0===o.indexOf("a_")){if(a=e.getAttribLocation(t,o),-1===a)throw"Program doesn't have required attribute: "+o;i[o.slice(2)]=a}else{if(0!==o.indexOf("u_"))throw"Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'";if(a=e.getUniformLocation(t,o),null===a)throw"Program doesn't have required uniform: "+o;i[o.slice(2)]=a}}return i},context:e}},Viva.Graph.View.WebglUtils=function(){},Viva.Graph.View.WebglUtils.prototype.parseColor=function(e){var t=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)t=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;t=255|parseInt(e.substr(1),16)<<8}else"number"==typeof e&&(t=e);return t},Viva.Graph.View._webglUtil=new Viva.Graph.View.WebglUtils,Viva.Graph.View.webglLine=function(e){return{color:Viva.Graph.View._webglUtil.parseColor(e)}},Viva.Graph.View.webglSquare=function(e,t){return{size:"number"==typeof e?e:10,color:Viva.Graph.View._webglUtil.parseColor(t)}},Viva.Graph.View.webglImage=function(e,t){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:t}},Viva.Graph.View.webglNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f=4,c=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,d=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),l=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),h=new ArrayBuffer(16*c),v=new Float32Array(h),p=new Uint32Array(h),m=0,g=function(){if((m+1)*c>=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(p),v=t,p=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(l,d),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;v[n*f]=t.x,v[n*f+1]=t.y,v[n*f+2]=e.size,p[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),m>e.id&&m>0&&i.copyArrayPart(p,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,d=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),v=0,p=new ArrayBuffer(16*d),m=new Float32Array(p),g=new Uint32Array(p),y=function(){if((v+1)*d>p.byteLength){var e=new ArrayBuffer(2*p.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,p=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,l),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),v+=1,o=e.id},removeLink:function(e){v>0&&(v-=1),v>e.id&&v>0&&r.copyArrayPart(g,e.id*c,v*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,p,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*v),o=v-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},d=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},l=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},v=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},p=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=l(e),o={offset:e};r.textureNumber>=s.length&&d();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;s.length>e;++e)s[e].isDirty=!1},remove:function(e){var t=a[e];if(!t)return!1;if(delete a[e],o-=1,o===t.offset)return!0;var n=l(t.offset),r=l(o);p(r,n);var i=a[f[o]];return i.offset=t.offset,f[t.offset]=f[o],v(),!0},getTextures:function(){return s},getCoordinates:function(e){return a[e]},load:function(e,t){if(a.hasOwnProperty(e))t(a[e]);else{var n=new window.Image,r=o;o+=1,n.crossOrigin="anonymous",n.onload=function(){v(),m(r,n,t)},n.src=e}}}},Viva.Graph.View.webglImageNodeProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=18,d=["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n"),l=["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n"),h=1024,v=0,p=new Float32Array(64),m=function(e,t){e.nativeObject&&n.deleteTexture(e.nativeObject);var r=n.createTexture();n.activeTexture(n["TEXTURE"+t]),n.bindTexture(n.TEXTURE_2D,r),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e.canvas),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR_MIPMAP_NEAREST),n.generateMipmap(n.TEXTURE_2D),n.uniform1i(o["sampler"+t],t),e.nativeObject=r},g=function(){if(e.isDirty){var t,n=e.getTextures();for(t=0;n.length>t;++t)(n[t].isDirty||!n[t].nativeObject)&&m(n[t],t);e.clearDirty()}};return{load:function(a){n=a,i=Viva.Graph.webgl(a),e=new Viva.Graph.View.webglAtlas(h),t=i.createProgram(l,d),n.useProgram(t),o=i.getLocations(t,["a_vertexPos","a_customAttributes","u_screenSize","u_transform","u_sampler0","u_sampler1","u_sampler2","u_sampler3","u_tilesPerTexture"]),n.uniform1f(o.tilesPerTexture,h),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.customAttributes),r=n.createBuffer()},position:function(e,t){var n=e.id*c;p[n]=t.x-e.size,p[n+1]=t.y-e.size,p[n+2]=4*e._offset,p[n+3]=t.x+e.size,p[n+4]=t.y-e.size,p[n+5]=4*e._offset+1,p[n+6]=t.x-e.size,p[n+7]=t.y+e.size,p[n+8]=4*e._offset+2,p[n+9]=t.x-e.size,p[n+10]=t.y+e.size,p[n+11]=4*e._offset+2,p[n+12]=t.x+e.size,p[n+13]=t.y-e.size,p[n+14]=4*e._offset+1,p[n+15]=t.x+e.size,p[n+16]=t.y+e.size,p[n+17]=4*e._offset+3},createNode:function(t){p=i.extendArray(p,v,c),v+=1;var n=e.getCoordinates(t.src);n?t._offset=n.offset:(t._offset=0,e.load(t.src,function(e){t._offset=e.offset}))},removeNode:function(t){v>0&&(v-=1),v>t.id&&v>0&&(t.src&&e.remove(t.src),i.copyArrayPart(p,t.id*c,v*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,p,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*v)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f=0,c=0,d=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],l=[],h=[],v={},p={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(d),g.updateTransform(d)},V=function(){d=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},N=function(e){e.fire("rescaled")};n=window.document.createElement("canvas");var P={getLinkUI:function(e){return p[e]},getNodeUI:function(e){return v[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return a=e,this},placeLink:function(e){return u=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){c>0&&m.render(),f>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(e,t){d[12]=2*e/i-1,d[13]=1-2*t/o,w()},addLink:function(e,t){var n=c++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,p[e.id]=r,r},addNode:function(e,t){var n=f++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),l[n]=r,v[e.id]=r,r},translateRel:function(e,t){d[12]+=2*d[0]*e/i/d[0],d[13]-=2*d[5]*t/o/d[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=d[12],r-=d[13],d[12]+=n*(1-e),d[13]+=r*(1-e),d[0]*=e,d[5]*=e,w(),N(this),d[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var f="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(f),f}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof s&&s(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){c>0&&(c-=1);var t=p[e.id];delete p[e.id],m.removeLink(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=h[c];h[n]=r,r.id=n}},releaseNode:function(e){f>0&&(f-=1);var t=v[e.id];delete v[e.id],g.removeNode(t);var n=t.id;if(f>n){if(0===f||f===n)return;var r=l[f];l[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;f>t;++t){var n=l[t];e.x=n.position.x,e.y=-n.position.y,a&&a(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;c>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,u&&u(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):s=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-d[12])/d[0],e.y=(e.y-d[13])/d[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;f>n;++n)if(t(l[n],e.x,e.y))return l[n].node;return null}};return Viva.Graph.Utils.events(P).extend(),P},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return t>r.x-i&&r.x+i>t&&n>r.y-i&&r.y+i>n}return!0},i=function(t){return e.getNodeAtClientPos(t,r)},o=null,a=[],u=[],s=[],f=[],c=[],d=[],l=[],h=Viva.Graph.Utils.events(window.document),v=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},p=function(e){return v(e),!1},m=function(e,t){var n,r;for(n=0;e.length>n;n+=1)if(r=e[n].apply(void 0,t))return!0},g=function(e){var r={x:0,y:0},g=null,y=+new Date,x=function(e){m(c,[g,e]),r.x=e.clientX,r.y=e.clientY},w=function(){h.stop("mousemove",x),h.stop("mouseup",w)},V=function(){n=e.getBoundingClientRect()};window.addEventListener("resize",V),V(),e.addEventListener("mousemove",function(e){if(!o){var t,s=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,t=i(r),t&&g!==t?(g=t,s=s||m(a,[g])):null===t&&g!==t&&(s=s||m(u,[g]),g=null),s&&v(e)}}),e.addEventListener("mousedown",function(e){var o,a=!1;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]?(a=m(s,o),h.on("mousemove",x),h.on("mouseup",w),t=window.document.onselectstart,window.document.onselectstart=p,g=o[0]):g=null,a&&v(e)}),e.addEventListener("mouseup",function(e){var o,a=+new Date;r.x=e.clientX-n.left,r.y=e.clientY-n.top,o=[i(r),e],o[0]&&(window.document.onselectstart=t,400>a-y&&o[0]===g?m(l,o):m(d,o),y=a,m(f,o)&&v(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&l.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file +var Viva=Viva||{};Viva.Graph=Viva.Graph||{},"undefined"!=typeof module&&module.exports&&(module.exports=Viva),Viva.Graph.version="0.6.0",Viva.lazyExtend=function(e,t){var n;if(e||(e={}),t)for(n in t)if(t.hasOwnProperty(n)){var r=e.hasOwnProperty(n),i=typeof t[n],o=!r||typeof e[n]!==i;o?e[n]=t[n]:"object"===i&&(e[n]=Viva.lazyExtend(e[n],t[n]))}return e},Viva.random=function(){var e,t=arguments[0];e="number"==typeof t?t:"string"==typeof t?t.length:+new Date;var n=function(){return e=e+2127912214+(e<<12)&4294967295,e=4294967295&(3345072700^e^e>>>19),e=e+374761393+(e<<5)&4294967295,e=4294967295&(e+3550635116^e<<9),e=e+4251993797+(e<<3)&4294967295,e=4294967295&(3042594569^e^e>>>16),(268435455&e)/268435456};return{next:function(e){return Math.floor(n()*e)},nextDouble:function(){return n()}}},Viva.randomIterator=function(e,t){return t=t||Viva.random(),{forEach:function(n){var r,i,o;for(r=e.length-1;r>0;--r)i=t.next(r+1),o=e[i],e[i]=e[r],e[r]=o,n(o);e.length&&n(e[0])},shuffle:function(){var n,r,i;for(n=e.length-1;n>0;--n)r=t.next(n+1),i=e[r],e[r]=e[n],e[n]=i;return e}}},Viva.BrowserInfo=function(){if("undefined"==typeof window||!window.hasOwnProperty("navigator"))return{browser:"",version:"0"};var e=window.navigator.userAgent.toLowerCase(),t=/(webkit)[ \/]([\w.]+)/,n=/(opera)(?:.*version)?[ \/]([\w.]+)/,r=/(msie) ([\w.]+)/,i=/(mozilla)(?:.*? rv:([\w.]+))?/,o=t.exec(e)||n.exec(e)||r.exec(e)||e.indexOf("compatible")<0&&i.exec(e)||[];return{browser:o[1]||"",version:o[2]||"0"}}(),Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.indexOfElementInArray=function(e,t){if(t.indexOf)return t.indexOf(e);var n,r=t.length;for(n=0;r>n;n+=1)if(t.hasOwnProperty(n)&&t[n]===e)return n;return-1},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.getDimension=function(e){if(!e)throw{message:"Cannot get dimensions of undefined container"};var t=e.clientWidth,n=e.clientHeight;return{left:0,top:0,width:t,height:n}},Viva.Graph.Utils.findElementPosition=function(e){var t=0,n=0;if(e.offsetParent)do t+=e.offsetLeft,n+=e.offsetTop;while(null!==(e=e.offsetParent));return[t,n]},Viva.Graph.Utils=Viva.Graph.Utils||{},Viva.Graph.Utils.events=function(e){var t=function(e){var t={};return e.fire=function(e,n){var r,i,o,a;if("string"!=typeof e)throw"Only strings can be used as even type";if(t.hasOwnProperty(e))for(r=t[e],a=0;an?r=-1:n>v&&(r=1),i(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=n,g(e),y(e)}},L=function(e){h=!1,s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),u=null,r&&r(e)},_=function(e,n){g(e),y(e),d=n.clientX,l=n.clientY,u=e.target||e.srcElement,t&&t(e,{x:d,y:l}),h||(h=!0,s.on("touchmove",G),s.on("touchend",L),s.on("touchcancel",L))},A=function(t){return console.log("Touch start for ",e),1===t.touches.length?_(t,t.touches[0]):void(2===t.touches.length&&(g(t),y(t),v=E(t.touches[0],t.touches[1])))};return f.on("mousedown",V),f.on("touchstart",A),{onStart:function(e){return t=e,this},onDrag:function(e){return n=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return P(e),this},release:function(){s.stop("mousemove",w),s.stop("mousedown",V),s.stop("mouseup",b),s.stop("touchmove",G),s.stop("touchend",L),s.stop("touchcancel",L),P(null)}}},Viva.Input=Viva.Input||{},Viva.Input.domInputManager=function(e,t){var n={};return{bindDragNDrop:function(e,r){var i;if(r){var o=t.getNodeUI(e.id);i=Viva.Graph.Utils.dragndrop(o),"function"==typeof r.onStart&&i.onStart(r.onStart),"function"==typeof r.onDrag&&i.onDrag(r.onDrag),"function"==typeof r.onStop&&i.onStop(r.onStop),n[e.id]=i}else(i=n[e.id])&&(i.release(),delete n[e.id])}}},Viva.Graph.Utils=Viva.Graph.Utils||{},function(){var e,t,n=0,r=["ms","moz","webkit","o"];for(t="undefined"!=typeof window?window:"undefined"!=typeof global?global:{setTimeout:function(){},clearTimeout:function(){}},e=0;e=0==g>=4?null:(f=u-o,d=i-a,h=a*o-i*u,v=f*e+d*t+h,p=f*n+d*r+h,0!==v&&0!==p&&v>=0==p>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*h-d*l,V.x=(0>w?w-x:w+x)/y,w=f*l-s*h,V.y=(0>w?w-x:w+x)/y,V)))},intersectRect:function(e,t,n,r,i,o,a,u){return this.intersect(e,t,e,r,i,o,a,u)||this.intersect(e,r,n,r,i,o,a,u)||this.intersect(n,r,n,t,i,o,a,u)||this.intersect(n,t,e,t,i,o,a,u)},convexHull:function(e){var t=function(e,t){var n,r,i=function(t){var n=t.x-e.x,r=t.y-e.y,i=n>0?1:-1;return i*n*n/(n*n+r*r)},o=t.sort(function(e,t){return i(t)-i(e)}),a=o[0],u=i(a),s=a.x-e.x,f=a.y-e.y,c=s*s+f*f;for(r=1;rn?o.splice(r,1):o.splice(r-1,1)):u=d}return o},n=function(e,t,n){return(n.x-e.x)*(t.y-e.y)-(n.y-e.y)*(t.x-e.x)<0};if(e.length<3)return e;var r,i=0;for(r=0;r0&&(a(e),o.length=0)},f=function(e,t){o.push({node:e,changeType:t})},c=function(e,t){o.push({link:e,changeType:t})},d={addNode:function(t,n){if("undefined"==typeof t)throw{message:"Invalid node identifier"};u();var i=this.getNode(t);return i?f(i,"update"):(i=new Viva.Graph.Node(t),r++,f(i,"add")),i.data=n,e[t]=i,s(this),i},addLink:function(e,r,i){u();var o=this.getNode(e)||this.addNode(e),a=this.getNode(r)||this.addNode(r),f=e.toString()+"👉 "+r.toString(),d=n.hasOwnProperty(f);(d||this.hasLink(e,r))&&(d||(n[f]=0),f+="@"+ ++n[f]);var l=new Viva.Graph.Link(e,r,i,f);return t.push(l),o.links.push(l),a.links.push(l),c(l,"add"),s(this),l},removeLink:function(e){if(!e)return!1;var n=Viva.Graph.Utils.indexOfElementInArray(e,t);if(0>n)return!1;u(),t.splice(n,1);var r=this.getNode(e.fromId),i=this.getNode(e.toId);return r&&(n=Viva.Graph.Utils.indexOfElementInArray(e,r.links),n>=0&&r.links.splice(n,1)),i&&(n=Viva.Graph.Utils.indexOfElementInArray(e,i.links),n>=0&&i.links.splice(n,1)),c(e,"remove"),s(this),!0},removeNode:function(t){var n=this.getNode(t);if(!n)return!1;for(u();n.links.length;){var i=n.links[0];this.removeLink(i)}e[t]=null,delete e[t],r--,f(n,"remove"),s(this)},getNode:function(t){return e[t]},getNodesCount:function(){return r},getLinksCount:function(){return t.length},getLinks:function(e){var t=this.getNode(e);return t?t.links:null},forEachNode:function(t){if("function"==typeof t){var n;for(n in e)if(t(e[n]))return}},forEachLinkedNode:function(t,n,r){var i,o,a,u=this.getNode(t);if(u&&u.links&&"function"==typeof n)if(r)for(i=0;in;++n)e(t[n])},beginUpdate:function(){u()},endUpdate:function(){s(this)},clear:function(){var e=this;e.beginUpdate(),e.forEachNode(function(t){e.removeNode(t.id)}),e.endUpdate()},hasLink:function(e,t){var n,r=this.getNode(e);if(!r)return null;for(n=0;nn;++n){var f=e.bodies[n],c=t/f.mass;f.velocity.x+=c*f.force.x,f.velocity.y+=c*f.force.y;var d=f.velocity.x,l=f.velocity.y,h=Math.sqrt(d*d+l*l);h>r&&(f.velocity.x=r*d/h,f.velocity.y=r*l/h),o=t*f.velocity.x,u=t*f.velocity.y,f.location.x+=o,f.location.y+=u,i+=Math.abs(o),a+=Math.abs(u)}return(i+a)/s}}},Viva.Graph.Physics.nbodyForce=function(e){function t(e,t){this.node=e,this.body=t}function n(){this.stack=[],this.popIdx=0}e=Viva.lazyExtend(e||{gravity:-1,theta:.8}),n.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var r=this.stack[this.popIdx];r?(r.node=e,r.body=n):this.stack[this.popIdx]=new t(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}};var r=e.gravity,i=[],o=new n,a=e.theta,u=Viva.random("5f4dcc3b5aa765d61d8327deb882cf99",75,20,63,108,65,76,65,72),s=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0,this.isInternal=!1},f=[],c=0,d=function(){var e;return f[c]?(e=f[c],e.quads[0]=null,e.quads[1]=null,e.quads[2]=null,e.quads[3]=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0,e.isInternal=!1):(e=new s,f[c]=e),++c,e},l=d(),h=function(e,t){var n=Math.abs(e.x-t.x),r=Math.abs(e.y-t.y);return 1e-8>n&&1e-8>r},v=function(e){for(o.reset(),o.push(l,e);!o.isEmpty();){var t=o.pop(),n=t.node,r=t.body;if(n.isInternal){var i=r.location.x,a=r.location.y;n.mass=n.mass+r.mass,n.massX=n.massX+r.mass*i,n.massY=n.massY+r.mass*a;var s=0,f=n.left,c=(n.right+f)/2,v=n.top,p=(n.bottom+v)/2;if(i>c){s+=1;var m=f;f=c,c+=c-m}if(a>p){s+=2;var g=v;v=p,p+=p-g}var y=n.quads[s];y||(y=d(),y.left=f,y.top=v,y.right=c,y.bottom=p,n.quads[s]=y),o.push(y,r)}else if(n.body){var x=n.body;if(n.body=null,n.isInternal=!0,h(x.location,r.location)){if(n.right-n.left<1e-8)return;do{var w=u.nextDouble(),V=(n.right-n.left)*w,b=(n.bottom-n.top)*w;x.location.x=n.left+V,x.location.y=n.top+b}while(h(x.location,r.location))}o.push(n,x),o.push(n,r)}else n.body=r}},p=function(e){var t,n,o,s,f=i,c=1,d=0,h=1;for(f[0]=l;c;){var v=f[d],p=v.body;c-=1,d+=1,p&&p!==e?(n=p.location.x-e.location.x,o=p.location.y-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),t=r*p.mass*e.mass/(s*s*s),e.force.x=e.force.x+t*n,e.force.y=e.force.y+t*o):(n=v.massX/v.mass-e.location.x,o=v.massY/v.mass-e.location.y,s=Math.sqrt(n*n+o*o),0===s&&(n=(u.nextDouble()-.5)/50,o=(u.nextDouble()-.5)/50,s=Math.sqrt(n*n+o*o)),(v.right-v.left)/ss&&(n=s),s>i&&(i=s),r>f&&(r=f),f>o&&(o=f)}var h=i-n,p=o-r;for(h>p?o=r+h:i=n+p,c=0,l=d(),l.left=n,l.right=i,l.top=r,l.bottom=o,t=u;t--;)v(a[t],l)};return{insert:v,init:m,update:p,options:function(e){return e?("number"==typeof e.gravity&&(r=e.gravity),"number"==typeof e.theta&&(a=e.theta),this):{gravity:r,theta:a}}}},Viva.Graph.Physics.dragForce=function(e){e||(e={});var t={coeff:e.coeff||.01};return{update:function(e){e.force.x-=t.coeff*e.velocity.x,e.force.y-=t.coeff*e.velocity.y},options:function(e){return e?("number"==typeof e.coeff&&(t.coeff=e.coeff),this):t}}},Viva.Graph.Physics.springForce=function(e){e=Viva.lazyExtend(e,{length:50,coeff:22e-5});var t=Viva.random("Random number 4.","Chosen by fair dice roll");return{update:function(n){var r=n.body1,i=n.body2,o=n.length<0?e.length:n.length,a=i.location.x-r.location.x,u=i.location.y-r.location.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(t.nextDouble()-.5)/50,u=(t.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-o,c=(!n.coeff||n.coeff<0?e.coeff:n.coeff)*f/s*n.weight;r.force.x+=c*a,r.force.y+=c*u,i.force.x+=-c*a,i.force.y+=-c*u},options:function(t){return t?("number"==typeof t.length&&(e.length=t.length),"number"==typeof t.coeff&&(e.coeff=t.coeff),this):e}}},Viva.Graph.Physics=Viva.Graph.Physics||{},Viva.Graph.Physics.forceSimulator=function(e){var t,n,r,i=e,o=[],a=[];return{speedLimit:1,bodies:o,accumulate:function(){var e,i;for(n.init(this),e=o.length;e--;)i=o[e],i.force.x=0,i.force.y=0,n.update(i),r.update(i);for(e=a.length;e--;)t.update(a[e])},run:function(e){return this.accumulate(),i.integrate(this,e)},addBody:function(e){if(!e)throw{message:"Cannot add null body to force simulator"};return o.push(e),e},removeBody:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,o);return 0>t?!1:o.splice(t,1)},addSpring:function(e,t,n,r,i){if(!e||!t)throw{message:"Cannot add null spring to force simulator"};if("number"!=typeof n)throw{message:"Spring length should be a number"};r="number"==typeof r?r:1;var o=new Viva.Graph.Physics.Spring(e,t,n,i>=0?i:-1,r);return a.push(o),o},removeSpring:function(e){if(!e)return!1;var t=Viva.Graph.Utils.indexOfElementInArray(e,a);return 0>t?!1:a.splice(t,1)},setNbodyForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};n=e},setDragForce:function(e){if(!e)throw{message:"Cannot add mighty (unknown) force to the simulator"};r=e},setSpringForce:function(e){if(!e)throw{message:"Cannot add unknown force to the simulator"};t=e}}},Viva.Graph.Layout=Viva.Graph.Layout||{},Viva.Graph.Layout.forceDirected=function(e,t){if(!e)throw{message:"Graph structure cannot be undefined"};t=Viva.lazyExtend(t,{springLength:80,springCoeff:2e-4,gravity:-1.2,theta:.8,dragCoeff:.02,springTransform:function(){},timeStep:20,stableThreshold:.009});var n=Viva.Graph.Physics.forceSimulator(Viva.Graph.Physics.eulerIntegrator()),r=Viva.Graph.Physics.nbodyForce({gravity:t.gravity,theta:t.theta}),i=Viva.Graph.Physics.springForce({length:t.springLength,coeff:t.springCoeff}),o=Viva.Graph.Physics.dragForce({coeff:t.dragCoeff}),a=new Viva.Graph.Rect,u=Viva.random("ted.com",103,114,101,97,116),s={},f=function(e){if(e.position)return e.position;var n=(a.x1+a.x2)/2,r=(a.y1+a.y2)/2,i=t.springLength;if(e.links&&e.links.length>0){var o=e.links[0],f=o.fromId!==e.id?s[o.fromId]:s[o.toId];f&&f.location&&(n=f.location.x,r=f.location.y)}return{x:n+u.next(i)-i/2,y:r+u.next(i)-i/2}},c=function(e){return s[e]},d=function(e){s[e]=null,delete s[e]},l={},h=function(t){var n=c(t);n.mass=1+e.getLinks(t).length/3},v=function(e){return e&&(e.isPinned||e.data&&e.data.isPinned)},p=function(e){return e.isPinned},m=function(t){var r=c(t);if(!r){var i=e.getNode(t);if(!i)return;r=new Viva.Graph.Physics.Body,s[t]=r;var o=f(i);r.loc(o),h(t),v(i)&&(r.isPinned=!0),n.addBody(r)}},g=function(e){m(e.id)},y=function(t){var r=c(t.id);r&&(d(t.id),n.removeBody(r),0===e.getNodesCount()&&(a.x1=a.y1=0,a.x2=a.y2=0))},x=function(e){h(e.fromId),h(e.toId);var r=c(e.fromId),i=c(e.toId),o=n.addSpring(r,i,-1,e.weight);t.springTransform(e,o),l[e.id]=o},w=function(t){var r=l[t.id];if(r){var i=e.getNode(t.fromId),o=e.getNode(t.toId);i&&h(i.id),o&&h(o.id),delete l[t.id],n.removeSpring(r)}},V=function(e){for(var t=0;tr&&(r=u.location.x),u.location.yi&&(i=u.location.y)}a.x1=t,a.x2=r,a.y1=n,a.y2=i}};return n.setSpringForce(i),n.setNbodyForce(r),n.setDragForce(o),b(),{run:function(e){var t;for(e=e||50,t=0;e>t;++t)this.step()},step:function(){var e=n.run(t.timeStep);return N(),et.x2&&(t.x2=e.x),e.yt.y2&&(t.y2=e.y)},a="function"==typeof Object.create?Object.create(null):{},u=function(e){e&&(a[e.id]=i(e),o(a[e.id],r))},s=function(){0!==e.getNodesCount()&&(r.x1=Number.MAX_VALUE,r.y1=Number.MAX_VALUE,r.x2=Number.MIN_VALUE,r.y2=Number.MIN_VALUE,e.forEachNode(u))},f=function(e){for(var t=0;t0)for(e=0;et,n)}),e.forEachNode(C),B(),o=Viva.Graph.Utils.events(e),o.on("changed",O)},q=function(){d=!1,B(),z(),V.stop("resize",F),b.removeAllListeners(),i.stop(),e.forEachLink(function(e){t.renderLinks&&T(e)}),e.forEachNode(function(e){S(e),I(e)}),u.dispose(),U()};return{run:function(e){return d||(w(),L(),_(),M(),X(),d=!0),E(e),this},reset:function(){s.resetScale(),_(),x.scale=1},pause:function(){g=!0,i.stop()},resume:function(){g=!1,i.restart()},rerender:function(){return N(),this},zoomOut:function(){return Y(!0)},zoomIn:function(){return Y(!1)},moveTo:function(e,t){s.graphCenterChanged(x.offsetX-e*x.scale,x.offsetY-t*x.scale),N()},getGraphics:function(){return s},dispose:function(){q()},on:function(e,t){return b.addEventListener(e,t),this},off:function(e,t){return b.removeEventListener(e,t),this}}},Viva.Graph.serializer=function(){var e=function(){if("undefined"==typeof JSON||!JSON.stringify||!JSON.parse)throw"JSON serializer is not defined."},t=function(e){return{id:e.id,data:e.data}},n=function(e){return{fromId:e.fromId,toId:e.toId,data:e.data}},r=function(e){return e},i=function(e){return e};return{storeToJSON:function(r,i,o){if(!r)throw"Graph is not defined";e(),i=i||t,o=o||n;var a={nodes:[],links:[]};return r.forEachNode(function(e){a.nodes.push(i(e))}),r.forEachLink(function(e){a.links.push(o(e))}),JSON.stringify(a)},loadFromJSON:function(t,n,o){if("string"!=typeof t)throw"String expected in loadFromJSON() method";e(),n=n||r,o=o||i;var a,u=JSON.parse(t),s=Viva.Graph.graph();if(!u||!u.nodes||!u.links)throw"Passed json string does not represent valid graph";for(a=0;an?void r.push({name:e,probability:i/t}):!0}),r},a=function(e){var t=[];return e.forEachNode(function(e){var n=Viva.Graph._community.occuranceMap(r);n.add(e.id),e.slpa={memory:n},t.push(e.id)}),t},u=function(e,n){var o,a=Viva.randomIterator(n,i),u=function(t){var n=e.getNode(t),i=Viva.Graph._community.occuranceMap(r);e.forEachLinkedNode(t,function(e){var t=e.slpa.memory.getRandomWord();i.add(t)});var o=i.getMostPopularFair();n.slpa.memory.add(o)};for(o=0;t-1>o;++o)a.forEach(u)},s=function(e){var r={};return e.forEachNode(function(e){var i,a=o(e.slpa.memory,n*t);for(i=0;ie?-1:e>n?1:0})},a=function(){r&&(o(),r=!1)};return{add:function(e){e=String(e),t.hasOwnProperty(e)?t[e]+=1:t[e]=1,n.push(e),r=!0},getWordCount:function(e){return t[e]||0},getMostPopularFair:function(){if(1===n.length)return n[0];a();var r,o=0;for(r=1;re)throw{message:"At least two nodes expected for complete graph"};var t,n,r=Viva.Graph.graph();for(r.Name="Complete K"+e,t=0;e>t;++t)for(n=t+1;e>n;++n)t!==n&&r.addLink(t,n);return r},completeBipartite:function(e,t){if(!e||!t||0>e||0>t)throw{message:"Graph dimensions are invalid. Number of nodes in each partition should be greater than 0"};var n,r,i=Viva.Graph.graph();for(i.Name="Complete K "+e+","+t,n=0;e>n;++n)for(r=e;e+t>r;++r)i.addLink(n,r); +return i},ladder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Ladder graph "+e,t=0;e-1>t;++t)n.addLink(t,t+1),n.addLink(e+t,e+t+1),n.addLink(t,e+t);return n.addLink(e-1,2*e-1),n},circularLadder:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t=this.ladder(e);return t.Name="Circular ladder graph "+e,t.addLink(0,e-1),t.addLink(e,2*e-1),t},grid:function(e,t){var n,r,i=Viva.Graph.graph();for(i.Name="Grid graph "+e+"x"+t,n=0;e>n;++n)for(r=0;t>r;++r){var o=n+r*e;n>0&&i.addLink(o,n-1+r*e),r>0&&i.addLink(o,n+(r-1)*e)}return i},path:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Path graph "+e,n.addNode(0),t=1;e>t;++t)n.addLink(t-1,t);return n},lollipop:function(e,t){if(!t||0>t||!e||0>e)throw{message:"Invalid number of nodes"};var n,r=this.complete(e);for(r.Name="Lollipop graph. Head x Path "+e+"x"+t,n=0;t>n;++n)r.addLink(e+n-1,e+n);return r},balancedBinTree:function(e){var t,n=Viva.Graph.graph(),r=Math.pow(2,e);for(n.Name="Balanced bin tree graph "+e,t=1;r>t;++t){var i=t,o=2*i,a=2*i+1;n.addLink(i,o),n.addLink(i,a)}return n},randomNoLinks:function(e){if(!e||0>e)throw{message:"Invalid number of nodes"};var t,n=Viva.Graph.graph();for(n.Name="Random graph, no Links: "+e,t=0;e>t;++t)n.addNode(t);return n}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.cssGraphics=function(){var e,t,n,r="OLD_IE",i=1,o=1,a=function(){var e,t,n=Viva.BrowserInfo.browser;switch(n){case"mozilla":e="Moz";break;case"webkit":e="webkit";break;case"opera":e="O";break;case"msie":if(t=Viva.BrowserInfo.version.split(".")[0],!(t>8))return r;e="ms"}return e?e+"Transform":null}(),u=function(){return a===r?function(e,t,n,r){var i=Math.cos(r),o=Math.sin(r);0>r&&(r=2*Math.PI+r),r=h.byteLength){var e=new ArrayBuffer(2*h.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(p),v=t,p=n,h=e}};return{load:function(o){t=o,i=Viva.Graph.webgl(o),e=i.createProgram(l,d),t.useProgram(e),r=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(r.vertexPos),t.enableVertexAttribArray(r.color),n=t.createBuffer()},position:function(e,t){var n=e.id;v[n*f]=t.x,v[n*f+1]=t.y,v[n*f+2]=e.size,p[n*f+3]=e.color},updateTransform:function(e){s=!0,u=e},updateSize:function(e,t){o=e,a=t,s=!0},removeNode:function(e){m>0&&(m-=1),e.id0&&i.copyArrayPart(p,e.id*f,m*f,f)},createNode:function(){g(),m+=1},replaceProperties:function(){},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,h,t.DYNAMIC_DRAW),s&&(s=!1,t.uniformMatrix4fv(r.transform,!1,u),t.uniform2f(r.screenSize,o,a)),t.vertexAttribPointer(r.vertexPos,3,t.FLOAT,!1,f*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(r.color,4,t.UNSIGNED_BYTE,!0,f*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,m)}}},Viva.Graph.View.webglLinkProgram=function(){var e,t,n,r,i,o,a,u,s,f,c=6,d=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),h=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),v=0,p=new ArrayBuffer(16*d),m=new Float32Array(p),g=new Uint32Array(p),y=function(){if((v+1)*d>p.byteLength){var e=new ArrayBuffer(2*p.byteLength),t=new Float32Array(e),n=new Uint32Array(e);n.set(g),m=t,g=n,p=e}};return{load:function(o){t=o,r=Viva.Graph.webgl(o),e=r.createProgram(h,l),t.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),t.enableVertexAttribArray(i.vertexPos),t.enableVertexAttribArray(i.color),n=t.createBuffer()},position:function(e,t,n){var r=e.id,i=r*c;m[i]=t.x,m[i+1]=t.y,g[i+2]=e.color,m[i+3]=n.x,m[i+4]=n.y,g[i+5]=e.color},createLink:function(e){y(),v+=1,o=e.id},removeLink:function(e){v>0&&(v-=1),e.id0&&r.copyArrayPart(g,e.id*c,v*c,c)},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){t.useProgram(e),t.bindBuffer(t.ARRAY_BUFFER,n),t.bufferData(t.ARRAY_BUFFER,p,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(i.transform,!1,s),t.uniform2f(i.screenSize,a,u)),t.vertexAttribPointer(i.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(i.color,4,t.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),t.drawArrays(t.LINES,0,2*v),o=v-1},bringToFront:function(e){o>e.id&&r.swapArrayPart(m,e.id*c,o*c,c),o>0&&(o-=1)},getFrontLinkId:function(){return o}}},Viva.Graph.View.Texture=function(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e},Viva.Graph.View.webglAtlas=function(e){var t,n,r=Math.sqrt(e||1024)<<0,i=r,o=1,a={},u=0,s=[],f=[],c=function(e){return 0===(e&e-1)},d=function(){var e=new Viva.Graph.View.Texture(r*i);s.push(e)},l=function(t){var n=t/e<<0,i=t%e,o=i/r<<0,a=i%r;return{textureNumber:n,row:o,col:a}},h=function(){n.isDirty=!0,u=0,t=null},v=function(){t&&(window.clearTimeout(t),u+=1,t=null),u>10?h():t=window.setTimeout(h,400)},p=function(e,t){var n=s[e.textureNumber].canvas,r=s[t.textureNumber].ctx,o=t.col*i,a=t.row*i;r.drawImage(n,e.col*i,e.row*i,i,i,o,a,i,i),s[e.textureNumber].isDirty=!0,s[t.textureNumber].isDirty=!0},m=function(e,t,n){var r=l(e),o={offset:e};r.textureNumber>=s.length&&d();var u=s[r.textureNumber];u.ctx.drawImage(t,r.col*i,r.row*i,i,i),f[e]=t.src,a[t.src]=o,u.isDirty=!0,n(o)};if(!c(e))throw"Tiles per texture should be power of two.";return n={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;e0&&(v-=1),t.id0&&(t.src&&e.remove(t.src),i.copyArrayPart(p,t.id*c,v*c,c))},replaceProperties:function(e,t){t._offset=e._offset},updateTransform:function(e){f=!0,s=e},updateSize:function(e,t){a=e,u=t,f=!0},render:function(){n.useProgram(t),n.bindBuffer(n.ARRAY_BUFFER,r),n.bufferData(n.ARRAY_BUFFER,p,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,s),n.uniform2f(o.screenSize,a,u)),n.vertexAttribPointer(o.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.customAttributes,1,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),g(),n.drawArrays(n.TRIANGLES,0,6*v)}}},Viva.Graph.View=Viva.Graph.View||{},Viva.Graph.View.webglGraphics=function(e){e=Viva.lazyExtend(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var t,n,r,i,o,a,u,s,f=0,c=0,d=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],l=[],h=[],v={},p={},m=Viva.Graph.View.webglLinkProgram(),g=Viva.Graph.View.webglNodeProgram(),y=function(){return Viva.Graph.View.webglSquare()},x=function(){return Viva.Graph.View.webglLine(3014898687)},w=function(){m.updateTransform(d),g.updateTransform(d)},V=function(){d=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},b=function(){t&&n&&(i=n.width=Math.max(t.offsetWidth,1),o=n.height=Math.max(t.offsetHeight,1),r&&r.viewport(0,0,i,o),m&&m.updateSize(i/2,o/2),g&&g.updateSize(i/2,o/2))},N=function(e){e.fire("rescaled")};n=window.document.createElement("canvas");var P={getLinkUI:function(e){return p[e]},getNodeUI:function(e){return v[e]},node:function(e){return"function"==typeof e?(y=e,this):void 0},link:function(e){return"function"==typeof e?(x=e,this):void 0},placeNode:function(e){return a=e,this},placeLink:function(e){return u=e,this},inputManager:Viva.Input.webglInputManager,beginRender:function(){},endRender:function(){c>0&&m.render(),f>0&&g.render()},bringLinkToFront:function(e){var t,n,r=m.getFrontLinkId();m.bringToFront(e),r>e.id&&(t=e.id,n=h[r],h[r]=h[t],h[r].id=r,h[t]=n,h[t].id=t)},graphCenterChanged:function(e,t){d[12]=2*e/i-1,d[13]=1-2*t/o,w()},addLink:function(e,t){var n=c++,r=x(e);return r.id=n,r.pos=t,m.createLink(r),h[n]=r,p[e.id]=r,r},addNode:function(e,t){var n=f++,r=y(e);return r.id=n,r.position=t,r.node=e,g.createNode(r),l[n]=r,v[e.id]=r,r},translateRel:function(e,t){d[12]+=2*d[0]*e/i/d[0],d[13]-=2*d[5]*t/o/d[5],w()},scale:function(e,t){var n=2*t.x/i-1,r=1-2*t.y/o;return n-=d[12],r-=d[13],d[12]+=n*(1-e),d[13]+=r*(1-e),d[0]*=e,d[5]*=e,w(),N(this),d[0]},resetScale:function(){return V(),r&&(b(),w()),this},init:function(a){var u={};if(e.preserveDrawingBuffer&&(u.preserveDrawingBuffer=!0),t=a,b(),V(),t.appendChild(n),r=n.getContext("experimental-webgl",u),!r){var f="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(f),f}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var c=e.clearColorValue;r.clearColor(c.r,c.g,c.b,c.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}m.load(r),m.updateSize(i/2,o/2),g.load(r),g.updateSize(i/2,o/2),w(),"function"==typeof s&&s(n)},release:function(e){n&&e&&e.removeChild(n)},isSupported:function(){var e=window.document.createElement("canvas"),t=e&&e.getContext&&e.getContext("experimental-webgl");return t},releaseLink:function(e){c>0&&(c-=1);var t=p[e.id];delete p[e.id],m.removeLink(t);var n=t.id;if(c>n){if(0===c||c===n)return;var r=h[c];h[n]=r,r.id=n}},releaseNode:function(e){f>0&&(f-=1);var t=v[e.id];delete v[e.id],g.removeNode(t);var n=t.id;if(f>n){if(0===f||f===n)return;var r=l[f];l[n]=r,r.id=n,g.replaceProperties(t,r)}},renderNodes:function(){for(var e={x:0,y:0},t=0;f>t;++t){var n=l[t];e.x=n.position.x,e.y=-n.position.y,a&&a(n,e),g.position(n,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},t={x:0,y:0},n=0;c>n;++n){var r=h[n],i=r.pos.from;t.x=i.x,t.y=-i.y,i=r.pos.to,e.x=i.x,e.y=-i.y,u&&u(r,t,e),m.position(r,t,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(n?e(n):s=e),n},setNodeProgram:function(e){if(!r&&e)g=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!r&&e)m=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/i-1,e.y=1-2*e.y/o,e.x=(e.x-d[12])/d[0],e.y=(e.y-d[13])/d[5],e.x*=i/2,e.y*=-o/2,e},getNodeAtClientPos:function(e,t){if("function"!=typeof t)return null;this.transformClientToGraphCoordinates(e);for(var n=0;f>n;++n)if(t(l[n],e.x,e.y))return l[n].node;return null}};return Viva.Graph.Utils.events(P).extend(),P},Viva.Graph.webglInputEvents=function(e){if(e.webglInputEvents)return e.webglInputEvents;var t,n,r=function(e,t,n){if(e&&e.size){var r=e.position,i=e.size;return r.x-ia-y&&o[0]===g?m(l,o):m(d,o),y=a,m(f,o)&&v(e))})};return e.getGraphicsRoot(g),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&a.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&s.push(e),this},mouseUp:function(e){return"function"==typeof e&&f.push(e),this},mouseMove:function(e){return"function"==typeof e&&c.push(e),this},click:function(e){return"function"==typeof e&&d.push(e),this},dblClick:function(e){return"function"==typeof e&&l.push(e),this},mouseCapture:function(e){o=e},releaseMouseCapture:function(){o=null}},e.webglInputEvents},Viva.Input=Viva.Input||{},Viva.Input.webglInputManager=function(e,t){var n=Viva.Graph.webglInputEvents(t),r=null,i={},o={x:0,y:0};return n.mouseDown(function(e,t){r=e,o.x=t.clientX,o.y=t.clientY,n.mouseCapture(r);var a=i[e.id];return a&&a.onStart&&a.onStart(t,o),!0}).mouseUp(function(e){n.releaseMouseCapture(r),r=null;var t=i[e.id];return t&&t.onStop&&t.onStop(),!0}).mouseMove(function(e,t){if(r){var n=i[r.id];return n&&n.onDrag&&n.onDrag(t,{x:t.clientX-o.x,y:t.clientY-o.y}),o.x=t.clientX,o.y=t.clientY,!0}}),{bindDragNDrop:function(e,t){i[e.id]=t,t||delete i[e.id]}}}; \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..86d6be1 --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,85 @@ +var gulp = require('gulp'); +var concat = require('gulp-concat'); +var path = require('path'); +var uglify = require('gulp-uglify'); +var rename = require('gulp-rename'); +var del = require('del'); + +var files = getFiles(); + +gulp.task('clean', clean); +gulp.task('build', concatenateFiles); +gulp.task('release', ['clean', 'build']); +gulp.task('default', watch); + +function watch() { + gulp.watch('src/**/*.js', ['build']); +} + +function clean(cb) { + del(['dist'], cb); +} + +function concatenateFiles() { + gulp.src(files) + .pipe(concat('vivagraph.js')) + .pipe(gulp.dest('./dist/')) + .pipe(rename('vivagraph.min.js')) + .pipe(uglify()) + .pipe(gulp.dest('./dist/')); +} + +function getFiles() { + // todo: this will be changed when we move to commonjs + return [ // core + "vivagraph.js", + "version.js", + "Utils/etc.js", + "Utils/browserInfo.js", + "Utils/indexOf.js", + "Utils/getDimensions.js", + "Utils/events.js", + "Input/dragndrop.js", + "Input/domInputManager.js", + "Input/spatialIndex.js", // TODO: Do I need this for SVG? + "Utils/timer.js", + "Utils/geom.js", + + "Core/primitives.js", + "Core/graph.js", + "Core/operations.js", + + "Physics/primitives.js", + "Physics/eulerIntegrator.js", + "Physics/Forces/nbodyForce.js", + "Physics/Forces/dragForce.js", + "Physics/Forces/springForce.js", + "Physics/forceSimulator.js", + "Layout/forceDirected.js", + "Layout/constant.js", + "View/renderer.js", + // extra + "Core/serializer.js", + "Algorithms/centrality.js", + "Algorithms/Community/community.js", + "Algorithms/Community/slpa.js", + "Core/generator.js", + "View/cssGraphics.js", + // svg + "Svg/svg.js", + "View/svgGraphics.js", + "View/svgNodeFactory.js", + // webgl + "WebGL/webgl.js", + "WebGL/webglUIModels.js", + "WebGL/webglNodeProgram.js", + "WebGL/webglLinkProgram.js", + "WebGL/webglImageNodeProgram.js", + "View/webglGraphics.js", + "WebGL/webglInputEvents.js", + "Input/webglInputManager.js"].map(toSrcFolder); +} + +function toSrcFolder(name) { + return path.join('src', name); +} diff --git a/package.json b/package.json index 83cd306..8d64254 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "doc": "docs" }, "scripts": { + "start": "gulp", "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { @@ -19,11 +20,10 @@ "author": "Andrei Kashcha", "license": "BSD", "devDependencies": { - "grunt": "~0.4.1", - "grunt-contrib-uglify": "~0.2.0", - "grunt-contrib-jshint": "~0.4.1", - "grunt-contrib-clean": "~0.4.0", - "grunt-contrib-concat": "~0.1.3", - "grunt-regarde": "~0.1.1" + "del": "^1.1.1", + "gulp": "^3.8.10", + "gulp-concat": "^2.4.2", + "gulp-rename": "^1.2.0", + "gulp-uglify": "^1.0.2" } } diff --git a/src/version.js b/src/version.js index 67454a9..c756618 100644 --- a/src/version.js +++ b/src/version.js @@ -1 +1 @@ -Viva.Graph.version = '0.5.8'; +Viva.Graph.version = '0.6.0'; From 5eb988836ea6def5efddbd8579401085d24dc260 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 27 Dec 2014 11:37:37 -0800 Subject: [PATCH 110/276] 0.6.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8d64254..ee1d080 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.5.8", + "version": "0.6.0", "description": "Graph Drawing Library", "main": "dist/vivagraph", "directories": { From 8462e6c7c993256f72782e559d9ead252a0fdb6f Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 28 Dec 2014 11:06:38 -0800 Subject: [PATCH 111/276] Migrated to tap for testing --- .jshintrc | 2 +- gulpfile.js | 8 +- package.json | 8 +- unit_tests/testRunner.html | 36 ---- unit_tests/test_Utils.js | 174 +++++++++------ unit_tests/test_constantLayout.js | 107 +++++----- unit_tests/test_forceBasedLayout.js | 61 +++--- unit_tests/test_graphCommunity.js | 198 +++++++++-------- unit_tests/test_graphConstructions.js | 296 +++++++++++++------------- unit_tests/test_graphOperations.js | 117 +++++----- unit_tests/test_graphSerialization.js | 173 ++++++++------- unit_tests/testing.js | 110 ---------- 12 files changed, 616 insertions(+), 674 deletions(-) delete mode 100644 unit_tests/testRunner.html delete mode 100644 unit_tests/testing.js diff --git a/.jshintrc b/.jshintrc index 604b7d3..667d574 100644 --- a/.jshintrc +++ b/.jshintrc @@ -4,7 +4,7 @@ "es5": true, "esnext": true, "bitwise": false, - "camelcase": true, + "camelcase": false, "curly": true, "eqeqeq": true, "immed": true, diff --git a/gulpfile.js b/gulpfile.js index 86d6be1..723cc27 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -4,12 +4,14 @@ var path = require('path'); var uglify = require('gulp-uglify'); var rename = require('gulp-rename'); var del = require('del'); +var run = require('gulp-run'); var files = getFiles(); gulp.task('clean', clean); gulp.task('build', concatenateFiles); -gulp.task('release', ['clean', 'build']); +gulp.task('test', test); +gulp.task('release', ['clean', 'build', 'test']); gulp.task('default', watch); function watch() { @@ -20,6 +22,10 @@ function clean(cb) { del(['dist'], cb); } +function test() { + new run.Command('npm test').exec(); +} + function concatenateFiles() { gulp.src(files) .pipe(concat('vivagraph.js')) diff --git a/package.json b/package.json index ee1d080..1b4bacf 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ }, "scripts": { "start": "gulp", - "test": "echo \"Error: no test specified\" && exit 1" + "test": "tap unit_tests/*.js" }, "repository": { "type": "git", @@ -24,6 +24,10 @@ "gulp": "^3.8.10", "gulp-concat": "^2.4.2", "gulp-rename": "^1.2.0", - "gulp-uglify": "^1.0.2" + "gulp-uglify": "^1.0.2", + "tap": "^0.4.13" + }, + "dependencies": { + "gulp-run": "^1.6.5" } } diff --git a/unit_tests/testRunner.html b/unit_tests/testRunner.html deleted file mode 100644 index 50ebc76..0000000 --- a/unit_tests/testRunner.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - VivaGraphs test page - - - - - - - - - - - - - - - - - diff --git a/unit_tests/test_Utils.js b/unit_tests/test_Utils.js index 958c813..f2f2357 100644 --- a/unit_tests/test_Utils.js +++ b/unit_tests/test_Utils.js @@ -1,68 +1,106 @@ -var test_Utils = function (test) { - return { - randomIteratorReturnsAllItems : function () { - var a = [1, 2, 3, 4, 5, 6], - aCopy = a.map(function (i) { return i; }), - shuffle = Viva.randomIterator(aCopy), - iterated = []; - shuffle.forEach(function (i) { - iterated.push(i); - test.assert(a.indexOf(i) !== -1, 'Shuffle iterator should return only items from original array. Unexpected ' + i); - }); - - test.assertEqual(iterated.length, a.length, 'Number of iterated items does not match number of original array items'); - }, - - lazyExtendDoesNotExtendExistingValues : function () { - var options = { age : 42 }; - - Viva.lazyExtend(options, { age : 24 }); - - test.assertEqual(options.age, 42, 'Should not touch properties when types match'); - }, - - lazyExtendUpdatesWhenTypeDoesNotMatch : function () { - var options = { age : '42' }; - - Viva.lazyExtend(options, { age : 24 }); - - test.assertEqual(options.age, 24, 'Should extend, because types are different'); - }, - - lazyExtendUpdatesWhenNewProperty : function () { - var options = { age : '42' }; - - Viva.lazyExtend(options, { newProperty : 24 }); - - test.assertEqual(options.age, '42', 'Should preserve old values'); - test.assertEqual(options.newProperty, 24, 'Should extend, because new property'); - }, - - lazyExtendDeepNewObjects : function () { - var options = { age : '42' }; - - Viva.lazyExtend(options, { nested : { name : 'deep'} }); - - test.assertEqual(options.age, '42', 'Should preserve old values'); - test.assertEqual(options.nested.name, 'deep', 'Should extend deep properties'); - }, - - lazyExtendDeepLogic : function () { - var options = { age : '42', nested: { first : 'Mark', age : '22'}}; - - Viva.lazyExtend(options, { nested : { first : '', last : 'Twain', age : 20} }); - - test.assertEqual(options.age, '42', 'Should preserve old values'); - test.assertEqual(options.nested.first, 'Mark', 'Should preserve deep properties with same types'); - test.assertEqual(options.nested.last, 'Twain', 'Should create new deep properties'); - test.assertEqual(options.nested.age, 20, 'Should fix deep properties with wrong types'); - }, - - lazyExtendCreatesNewObject : function () { - var options, - extended = Viva.lazyExtend(options, {}); - - test.assert(extended, 'New object should be created'); - } - }; -}; \ No newline at end of file +var test = require('tap').test; +var Viva = require('../dist/vivagraph.js'); + +test('randomIteratorReturnsAllItems', function(t) { + var a = [1, 2, 3, 4, 5, 6], + aCopy = a.map(function(i) { + return i; + }), + shuffle = Viva.randomIterator(aCopy), + iterated = []; + shuffle.forEach(function(i) { + iterated.push(i); + t.ok(a.indexOf(i) !== -1, 'Shuffle iterator should return only items from original array. Unexpected ' + i); + }); + + t.equals(iterated.length, a.length, 'Number of iterated items does not match number of original array items'); + t.end(); +}); + +test('lazyExtendDoesNotExtendExistingValues', function(t) { + var options = { + age: 42 + }; + + Viva.lazyExtend(options, { + age: 24 + }); + + t.equals(options.age, 42, 'Should not touch properties when types match'); + t.end(); +}); + +test('lazyExtendUpdatesWhenTypeDoesNotMatch', function(t) { + var options = { + age: '42' + }; + + Viva.lazyExtend(options, { + age: 24 + }); + + t.equals(options.age, 24, 'Should extend, because types are different'); + t.end(); +}); + +test('lazyExtendUpdatesWhenNewProperty', function(t) { + var options = { + age: '42' + }; + + Viva.lazyExtend(options, { + newProperty: 24 + }); + + t.equals(options.age, '42', 'Should preserve old values'); + t.equals(options.newProperty, 24, 'Should extend, because new property'); + t.end(); +}); + +test('lazyExtendDeepNewObjects', function(t) { + var options = { + age: '42' + }; + + Viva.lazyExtend(options, { + nested: { + name: 'deep' + } + }); + + t.equals(options.age, '42', 'Should preserve old values'); + t.equals(options.nested.name, 'deep', 'Should extend deep properties'); + t.end(); +}); + +test('lazyExtendDeepLogic', function(t) { + var options = { + age: '42', + nested: { + first: 'Mark', + age: '22' + } + }; + + Viva.lazyExtend(options, { + nested: { + first: '', + last: 'Twain', + age: 20 + } + }); + + t.equals(options.age, '42', 'Should preserve old values'); + t.equals(options.nested.first, 'Mark', 'Should preserve deep properties with same types'); + t.equals(options.nested.last, 'Twain', 'Should create new deep properties'); + t.equals(options.nested.age, 20, 'Should fix deep properties with wrong types'); + t.end(); +}); + +test('lazyExtendCreatesNewObject', function(t) { + var options, + extended = Viva.lazyExtend(options, {}); + + t.ok(extended, 'New object should be created'); + t.end(); +}); diff --git a/unit_tests/test_constantLayout.js b/unit_tests/test_constantLayout.js index 84579ad..925aa80 100644 --- a/unit_tests/test_constantLayout.js +++ b/unit_tests/test_constantLayout.js @@ -1,56 +1,57 @@ -/*global Viva*/ - /** - * Testing Viva.Graph.Layout.constant behavior. + * Testing Viva.Graph.Layout.constant behavior. */ -var test_constantLayout = function(test) { - return { - nodePositionGeneratedByDefault: function() { - var graph = Viva.Graph.generator().path(10), - layout = Viva.Graph.Layout.constant(graph); - - layout.run(); - - graph.forEachNode(function(node) { - var position = layout.getNodePosition(node.id); - test.assert(position, 'All nodes expected to have some position'); - test.assert(typeof position.x === 'number', 'Node position does not have a valid x position'); - test.assert(typeof position.y === 'number', 'Node position does not have a valid y position'); - }); - }, - - nodePositionUsesCustomCallback: function() { - var graph = Viva.Graph.generator().path(10), - layout = Viva.Graph.Layout.constant(graph), - placeNodeCallback = function() { - return new Viva.Graph.Point2d(42, 42); // all nodes should be placed at the same position. - }; - - layout.placeNode(placeNodeCallback); - layout.run(); - - graph.forEachNode(function(node) { - var position = layout.getNodePosition(node.id); - test.assertEqual(position.x, 42, 'Node position does not have a valid x position'); - test.assertEqual(position.y, 42, 'Node position does not have a valid y position'); - }); - }, - - getGraphRectReflectsDefaultSettings: function() { - var graph = Viva.Graph.generator().path(10), - layoutSettings = { - maxX: 42, - maxY: 42 - }, - layout = Viva.Graph.Layout.constant(graph, layoutSettings); - - layout.run(); - - graph.forEachNode(function(node) { - var position = layout.getNodePosition(node.id); - test.assert(position.x <= layoutSettings.maxX, 'Node position does not have a valid x position'); - test.assert(position.y <= layoutSettings.maxY, 'Node position does not have a valid y position'); - }); - } + +var test = require('tap').test; +var Viva = require('../dist/vivagraph.js'); + +test('nodePositionGeneratedByDefault', function(t) { + var graph = Viva.Graph.generator().path(10), + layout = Viva.Graph.Layout.constant(graph); + + layout.run(); + + graph.forEachNode(function(node) { + var position = layout.getNodePosition(node.id); + t.ok(position, 'All nodes expected to have some position'); + t.ok(typeof position.x === 'number', 'Node position does not have a valid x position'); + t.ok(typeof position.y === 'number', 'Node position does not have a valid y position'); + }); + t.end(); +}); + +test('nodePositionUsesCustomCallback', function(t) { + var graph = Viva.Graph.generator().path(10), + layout = Viva.Graph.Layout.constant(graph), + placeNodeCallback = function() { + return new Viva.Graph.Point2d(42, 42); // all nodes should be placed at the same position. }; -}; + + layout.placeNode(placeNodeCallback); + layout.run(); + + graph.forEachNode(function(node) { + var position = layout.getNodePosition(node.id); + t.equals(position.x, 42, 'Node position does not have a valid x position'); + t.equals(position.y, 42, 'Node position does not have a valid y position'); + }); + t.end(); +}); + +test('getGraphRectReflectsDefaultSettings', function(t) { + var graph = Viva.Graph.generator().path(10), + layoutSettings = { + maxX: 42, + maxY: 42 + }, + layout = Viva.Graph.Layout.constant(graph, layoutSettings); + + layout.run(); + + graph.forEachNode(function(node) { + var position = layout.getNodePosition(node.id); + t.ok(position.x <= layoutSettings.maxX, 'Node position does not have a valid x position'); + t.ok(position.y <= layoutSettings.maxY, 'Node position does not have a valid y position'); + }); + t.end(); +}); diff --git a/unit_tests/test_forceBasedLayout.js b/unit_tests/test_forceBasedLayout.js index ae59dcc..68aa883 100644 --- a/unit_tests/test_forceBasedLayout.js +++ b/unit_tests/test_forceBasedLayout.js @@ -1,31 +1,34 @@ -var test_forceBasedLayout = function(test) { - var assertGraphHasPositions = function(graph, layout) { - graph.forEachNode(function(node) { - var position = layout.getNodePosition(node.id); - test.assert(position, 'All nodes expected to have some position'); - test.assert(typeof position.x === 'number', 'Node position does not have a valid x position'); - test.assert(typeof position.y === 'number', 'Node position does not have a valid y position'); - }); - }; - return { - forceAttributesInitialized : function () { - var graph = Viva.Graph.generator().path(2); +var test = require('tap').test; +var Viva = require('../dist/vivagraph.js'); - var layout = Viva.Graph.Layout.forceDirected(graph); - assertGraphHasPositions(graph, layout); - }, - graphIsMonitored : function () { - var graph = Viva.Graph.graph(); +test('forceAttributesInitialized', function(t) { + var graph = Viva.Graph.generator().path(2); - var layout = Viva.Graph.Layout.forceDirected(graph); - graph.addNode(1); - assertGraphHasPositions(graph, layout); - graph.addNode(2); - assertGraphHasPositions(graph, layout); - graph.addLink(1, 2); - assertGraphHasPositions(graph, layout); - graph.removeNode(1); - assertGraphHasPositions(graph, layout); - } - }; -}; + var layout = Viva.Graph.Layout.forceDirected(graph); + assertGraphHasPositions(graph, layout, t); + t.end(); +}); + +test('graphIsMonitored', function(t) { + var graph = Viva.Graph.graph(); + + var layout = Viva.Graph.Layout.forceDirected(graph); + graph.addNode(1); + assertGraphHasPositions(graph, layout, t); + graph.addNode(2); + assertGraphHasPositions(graph, layout, t); + graph.addLink(1, 2); + assertGraphHasPositions(graph, layout, t); + graph.removeNode(1); + assertGraphHasPositions(graph, layout, t); + t.end(); +}); + +function assertGraphHasPositions(graph, layout, test) { + graph.forEachNode(function(node) { + var position = layout.getNodePosition(node.id); + test.ok(position, 'All nodes expected to have some position'); + test.ok(typeof position.x === 'number', 'Node position does not have a valid x position'); + test.ok(typeof position.y === 'number', 'Node position does not have a valid y position'); + }); +} diff --git a/unit_tests/test_graphCommunity.js b/unit_tests/test_graphCommunity.js index 687d94e..8b8ca2f 100644 --- a/unit_tests/test_graphCommunity.js +++ b/unit_tests/test_graphCommunity.js @@ -1,94 +1,104 @@ -/*global Viva, console*/ - -var test_graphCommunity = function(test){ - - return { - - occuranceMapCountsWords : function() { - var map = Viva.Graph._community.occuranceMap(); - for (var i = 0; i < 15; ++i) { - map.add('hello'); - } - map.add('world'); - - var helloCount = map.getWordCount('hello'), - worldCount = map.getWordCount('world'), - randomWordCount = map.getWordCount('he-he'); - - test.assertEqual(helloCount, 15, 'Hello word should be added 15 times'); - test.assertEqual(worldCount, 1, 'Only one occurance of world should be in the map'); - test.assertEqual(randomWordCount, 0, 'This word should not be in the map!'); - }, - - occuranceMapFindsMostPopularWord : function() { - var map = Viva.Graph._community.occuranceMap(); - - map.add('hello'); map.add('world'); map.add('!'); - map.add('hello'); map.add('world'); - map.add('hello'); - - var mostPopular = map.getMostPopularFair(); - - test.assertEqual(mostPopular, 'hello', 'Unexpected most popular word'); - }, - - occuranceMapFindsMostPopularWordWithSameRank : function() { - var map = Viva.Graph._community.occuranceMap(); - - for (var i = 0; i < 100; ++i) { - if (i < 50) { - map.add('hello'); - } else { - map.add('world'); - } - } - - var helloFound = false, - worldFound = false; - for(i = 0; i < 10; ++i){ - var word = map.getMostPopularFair(); - if (word === 'hello') { helloFound = true; } - if (word === 'world') { worldFound = true; } - } - - test.assert(helloFound && worldFound, 'Both words should appear. Well. Potentially...This is non-determenistic test'); - }, - - occuranceMapReturnsRandomWord : function() { - var map = Viva.Graph._community.occuranceMap(), - dictionary = {}; - - for (var i = 0; i < 15; ++i) { - var word = 'hello' + i; - map.add(word); - dictionary[word] = 1; - } - - for (i = 0; i < 15; ++i) { - var actual = map.getRandomWord(); - test.assert(dictionary.hasOwnProperty(actual), 'The random word is not expected'); - } - }, - - occuranceMapEnumeratesAllWords : function() { - var map = Viva.Graph._community.occuranceMap(), - dictionary = {}; - - map.add('hello'); map.add('world'); map.add('!'); - map.add('hello'); map.add('world'); - map.add('hello'); - - var prevCount = 4; - map.forEachUniqueWord(function(word, count) { - test.assert(count <= prevCount, "Enumeration should go in non increasing order"); - test.assert(!dictionary.hasOwnProperty(word), "Enumeration should go through unique words only"); - - dictionary[word] = count; - }); - - test.assert(dictionary.hello, 3, "Unexpected number of 'hello'"); - test.assert(dictionary.world, 2, "Unexpected number of 'world'"); - test.assert(dictionary['!'], 1, "Unexpected number of '!'"); - } - }; -}; \ No newline at end of file +var test = require('tap').test; +var Viva = require('../dist/vivagraph.js'); + +test('occuranceMapCountsWords', function(t) { + var map = Viva.Graph._community.occuranceMap(); + for (var i = 0; i < 15; ++i) { + map.add('hello'); + } + map.add('world'); + + var helloCount = map.getWordCount('hello'), + worldCount = map.getWordCount('world'), + randomWordCount = map.getWordCount('he-he'); + + t.equals(helloCount, 15, 'Hello word should be added 15 times'); + t.equals(worldCount, 1, 'Only one occurance of world should be in the map'); + t.equals(randomWordCount, 0, 'This word should not be in the map!'); + t.end(); +}); + +test('occuranceMapFindsMostPopularWord', function(t) { + var map = Viva.Graph._community.occuranceMap(); + + map.add('hello'); + map.add('world'); + map.add('!'); + map.add('hello'); + map.add('world'); + map.add('hello'); + + var mostPopular = map.getMostPopularFair(); + + t.equals(mostPopular, 'hello', 'Unexpected most popular word'); + t.end(); +}); + +test('occuranceMapFindsMostPopularWordWithSameRank', function(t) { + var map = Viva.Graph._community.occuranceMap(); + + for (var i = 0; i < 100; ++i) { + if (i < 50) { + map.add('hello'); + } else { + map.add('world'); + } + } + + var helloFound = false, + worldFound = false; + for (i = 0; i < 10; ++i) { + var word = map.getMostPopularFair(); + if (word === 'hello') { + helloFound = true; + } + if (word === 'world') { + worldFound = true; + } + } + + t.ok(helloFound && worldFound, 'Both words should appear. Well. Potentially...This is non-determenistic test'); + t.end(); +}); + +test('occuranceMapReturnsRandomWord', function(t) { + var map = Viva.Graph._community.occuranceMap(), + dictionary = {}; + + for (var i = 0; i < 15; ++i) { + var word = 'hello' + i; + map.add(word); + dictionary[word] = 1; + } + + for (i = 0; i < 15; ++i) { + var actual = map.getRandomWord(); + t.ok(dictionary.hasOwnProperty(actual), 'The random word is not expected'); + } + t.end(); +}); + +test('occuranceMapEnumeratesAllWords', function(t) { + var map = Viva.Graph._community.occuranceMap(), + dictionary = {}; + + map.add('hello'); + map.add('world'); + map.add('!'); + map.add('hello'); + map.add('world'); + map.add('hello'); + + var prevCount = 4; + map.forEachUniqueWord(function(word, count) { + t.ok(count <= prevCount, "Enumeration should go in non increasing order"); + t.ok(!dictionary.hasOwnProperty(word), "Enumeration should go through unique words only"); + + dictionary[word] = count; + }); + + t.equals(dictionary.hello, 3, "Unexpected number of 'hello'"); + t.equals(dictionary.world, 2, "Unexpected number of 'world'"); + t.equals(dictionary['!'], 1, "Unexpected number of '!'"); + t.end(); +}); diff --git a/unit_tests/test_graphConstructions.js b/unit_tests/test_graphConstructions.js index 6499495..59a7209 100644 --- a/unit_tests/test_graphConstructions.js +++ b/unit_tests/test_graphConstructions.js @@ -1,145 +1,151 @@ -/*global Viva, console*/ - -var test_GraphConstructions = function(test){ - return { - addNode : function() { - var graph = Viva.Graph.graph(); - var customData = '31337'; - - var node = graph.addNode(1, customData); - - test.assertEqual(graph.getNodesCount(), 1, 'addNode failed'); - test.assertEqual(graph.getNode(1), node, 'invalid node returned by addNode (or getNode)'); - test.assertEqual(node.data, customData, 'data was not set properly'); - test.assertEqual(node.id, 1, 'node id was not set properly'); - }, - - addLink : function() { - var graph = Viva.Graph.graph(); - - var link = graph.addLink(1, 2), - firstNodeLinks = graph.getLinks(1), - secondNodeLinks = graph.getLinks(2); - - test.assertEqual(graph.getNodesCount(), 2, 'addLink failed'); - test.assertEqual(firstNodeLinks.length, 1, 'number of links of the first node is wrong'); - test.assertEqual(secondNodeLinks.length, 1, 'number of links of the second node is wrong'); - test.assertEqual(link, firstNodeLinks[0], 'invalid link in the first node'); - test.assertEqual(link, secondNodeLinks[0], 'invalid link in the second node'); - }, - - addOneNodeFireChanged : function() { - var graph = Viva.Graph.graph(); - var testNodeId = 'hello world'; - var graphEvents = Viva.Graph.Utils.events(graph); - graphEvents.on('changed', function(changes) { - test.assert(changes && changes.length === 1, "Only one change should be recorded"); - test.assertEqual(changes[0].node.id, testNodeId, "Wrong node change notification"); - test.assertEqual(changes[0].changeType, 'add', "Add change type expected."); - }); - - graph.addNode(testNodeId); - }, - - addLinkFireChanged : function() { - var graph = Viva.Graph.graph(); - var fromId = 1, toId = 2; - var graphEvents = Viva.Graph.Utils.events(graph); - graphEvents.on('changed', function(changes) { - test.assert(changes && changes.length === 3, "Three change should be recorded: node, node and link"); - test.assertEqual(changes[2].link.fromId, fromId, "Wrong link from Id"); - test.assertEqual(changes[2].link.toId, toId, "Wrong link toId"); - test.assertEqual(changes[2].changeType, 'add', "Add change type expected."); - }); - - graph.addLink(fromId, toId); - }, - - removeIsolatedNode : function() { - var graph = Viva.Graph.graph(); - graph.addNode(1); - - graph.removeNode(1); - - test.assertEqual(graph.getNodesCount(), 0, 'Remove operation failed'); - }, - - removeLink : function() { - var graph = Viva.Graph.graph(); - var link = graph.addLink(1, 2); - - graph.removeLink(link); - - test.assertEqual(graph.getNodesCount(), 2, 'remove link should not remove nodes'); - test.assertEqual(graph.getLinks(1).length, 0, 'link should be removed from the first node'); - test.assertEqual(graph.getLinks(2).length, 0, 'link should be removed from the second node'); - graph.forEachLink(function(link){ - test.assertFail('No links should be in graph'); - }); - }, - - removeIsolatedNodeFireChanged : function() { - var graph = Viva.Graph.graph(); - var graphEvents = Viva.Graph.Utils.events(graph); - graph.addNode(1); - - graphEvents.on('changed', function(changes) { - test.assert(changes && changes.length === 1, "One change should be recorded: node removed"); - test.assertEqual(changes[0].node.id, 1, "Wrong node Id"); - test.assertEqual(changes[0].changeType, 'remove', "'remove' change type expected."); - }); - - graph.removeNode(1); - }, - - removeLinkFireChanged : function() { - var graph = Viva.Graph.graph(); - var graphEvents = Viva.Graph.Utils.events(graph); - var link = graph.addLink(1, 2); - - graphEvents.on('changed', function(changes) { - test.assert(changes && changes.length === 1, "One change should be recorded: link removed"); - test.assertEqual(changes[0].link, link, "Wrong link removed"); - test.assertEqual(changes[0].changeType, 'remove', "'remove' change type expected."); - }); - - graph.removeLink(1); - }, - - removeLinkedNodeFireChanged : function() { - var graph = Viva.Graph.graph(), - graphEvents = Viva.Graph.Utils.events(graph), - link = graph.addLink(1, 2), - nodeIdToRemove = 1; - - graphEvents.on('changed', function(changes) { - test.assert(changes && changes.length === 2, "Two changes should be recorded: link and node removed"); - test.assertEqual(changes[0].link, link, "Wrong link removed"); - test.assertEqual(changes[0].changeType, 'remove', "'remove' change type expected."); - test.assertEqual(changes[1].node.id, nodeIdToRemove, "Wrong node removed"); - test.assertEqual(changes[1].changeType, 'remove', "'remove' change type expected."); - }); - - graph.removeNode(nodeIdToRemove); - }, - - removeNodeWithManyLinks : function() { - var graph = Viva.Graph.graph(), - graphEvents = Viva.Graph.Utils.events(graph), - link12 = graph.addLink(1, 2), - link13 = graph.addLink(1, 3), - nodeIdToRemove = 1; - - graph.removeNode(1); - - test.assertEqual(graph.getNodesCount(), 2, 'remove link should remove one node only'); - test.assertEqual(graph.getLinks(1), null, 'link should be removed from the first node'); - test.assertEqual(graph.getLinks(2).length, 0, 'link should be removed from the second node'); - test.assertEqual(graph.getLinks(3).length, 0, 'link should be removed from the third node'); - graph.forEachLink(function(link) { - test.assertFail('No links should be in graph'); - }); - - } - }; -}; \ No newline at end of file +var test = require('tap').test; +var Viva = require('../dist/vivagraph.js'); + +test('addNode', function(t) { + var graph = Viva.Graph.graph(); + var customData = '31337'; + + var node = graph.addNode(1, customData); + + t.equals(graph.getNodesCount(), 1, 'addNode failed'); + t.equals(graph.getNode(1), node, 'invalid node returned by addNode (or getNode)'); + t.equals(node.data, customData, 'data was not set properly'); + t.equals(node.id, 1, 'node id was not set properly'); + t.end(); +}); + +test('addLink', function(t) { + var graph = Viva.Graph.graph(); + + var link = graph.addLink(1, 2), + firstNodeLinks = graph.getLinks(1), + secondNodeLinks = graph.getLinks(2); + + t.equals(graph.getNodesCount(), 2, 'addLink failed'); + t.equals(firstNodeLinks.length, 1, 'number of links of the first node is wrong'); + t.equals(secondNodeLinks.length, 1, 'number of links of the second node is wrong'); + t.equals(link, firstNodeLinks[0], 'invalid link in the first node'); + t.equals(link, secondNodeLinks[0], 'invalid link in the second node'); + t.end(); +}); + +test('addOneNodeFireChanged', function(t) { + var graph = Viva.Graph.graph(); + var testNodeId = 'hello world'; + var graphEvents = Viva.Graph.Utils.events(graph); + graphEvents.on('changed', function(changes) { + t.ok(changes && changes.length === 1, "Only one change should be recorded"); + t.equals(changes[0].node.id, testNodeId, "Wrong node change notification"); + t.equals(changes[0].changeType, 'add', "Add change type expected."); + }); + + graph.addNode(testNodeId); + t.end(); +}); + +test('addLinkFireChanged', function(t) { + var graph = Viva.Graph.graph(); + var fromId = 1, + toId = 2; + var graphEvents = Viva.Graph.Utils.events(graph); + graphEvents.on('changed', function(changes) { + t.ok(changes && changes.length === 3, "Three change should be recorded: node, node and link"); + t.equals(changes[2].link.fromId, fromId, "Wrong link from Id"); + t.equals(changes[2].link.toId, toId, "Wrong link toId"); + t.equals(changes[2].changeType, 'add', "Add change type expected."); + }); + + graph.addLink(fromId, toId); + t.end(); +}); + +test('removeIsolatedNode', function(t) { + var graph = Viva.Graph.graph(); + graph.addNode(1); + + graph.removeNode(1); + + t.equals(graph.getNodesCount(), 0, 'Remove operation failed'); + t.end(); +}); + +test('removeLink', function(t) { + var graph = Viva.Graph.graph(); + var link = graph.addLink(1, 2); + + graph.removeLink(link); + + t.equals(graph.getNodesCount(), 2, 'remove link should not remove nodes'); + t.equals(graph.getLinks(1).length, 0, 'link should be removed from the first node'); + t.equals(graph.getLinks(2).length, 0, 'link should be removed from the second node'); + graph.forEachLink(function() { + t.fail('No links should be in graph'); + }); + t.end(); +}); + +test('removeIsolatedNodeFireChanged', function(t) { + var graph = Viva.Graph.graph(); + var graphEvents = Viva.Graph.Utils.events(graph); + graph.addNode(1); + + graphEvents.on('changed', function(changes) { + t.ok(changes && changes.length === 1, "One change should be recorded: node removed"); + t.equals(changes[0].node.id, 1, "Wrong node Id"); + t.equals(changes[0].changeType, 'remove', "'remove' change type expected."); + }); + + graph.removeNode(1); + t.end(); +}); + +test('removeLinkFireChanged', function(t) { + var graph = Viva.Graph.graph(); + var graphEvents = Viva.Graph.Utils.events(graph); + var link = graph.addLink(1, 2); + + graphEvents.on('changed', function(changes) { + t.ok(changes && changes.length === 1, "One change should be recorded: link removed"); + t.equals(changes[0].link, link, "Wrong link removed"); + t.equals(changes[0].changeType, 'remove', "'remove' change type expected."); + }); + + graph.removeLink(1); + t.end(); +}); + +test('removeLinkedNodeFireChanged', function(t) { + var graph = Viva.Graph.graph(), + graphEvents = Viva.Graph.Utils.events(graph), + link = graph.addLink(1, 2), + nodeIdToRemove = 1; + + graphEvents.on('changed', function(changes) { + t.ok(changes && changes.length === 2, "Two changes should be recorded: link and node removed"); + t.equals(changes[0].link, link, "Wrong link removed"); + t.equals(changes[0].changeType, 'remove', "'remove' change type expected."); + t.equals(changes[1].node.id, nodeIdToRemove, "Wrong node removed"); + t.equals(changes[1].changeType, 'remove', "'remove' change type expected."); + }); + + graph.removeNode(nodeIdToRemove); + t.end(); +}); + +test('removeNodeWithManyLinks', function(t) { + var graph = Viva.Graph.graph(); + + graph.addLink(1, 2); + graph.addLink(1, 3); + graph.removeNode(1); + + t.equals(graph.getNodesCount(), 2, 'remove link should remove one node only'); + t.equals(graph.getLinks(1), null, 'link should be removed from the first node'); + t.equals(graph.getLinks(2).length, 0, 'link should be removed from the second node'); + t.equals(graph.getLinks(3).length, 0, 'link should be removed from the third node'); + graph.forEachLink(function() { + t.fail('No links should be in graph'); + }); + + t.end(); +}); diff --git a/unit_tests/test_graphOperations.js b/unit_tests/test_graphOperations.js index 5aee539..8a011c3 100644 --- a/unit_tests/test_graphOperations.js +++ b/unit_tests/test_graphOperations.js @@ -1,58 +1,59 @@ -/*global Viva, console*/ - -var test_GraphOperations = function(test){ - - return { - twoNodeGraphDensity : function() { - var graph = Viva.Graph.graph(), - operations = Viva.Graph.operations(); - - graph.addLink(1, 2); - - var density = operations.density(graph); - - test.assertEqual(density, 1, 'Density of two node graph should be 1'); - }, - - completeGraphDensity : function() { - var operations = Viva.Graph.operations(); - - for(var i = 2; i < 10; ++i) { - var graph = Viva.Graph.generator().complete(i); - var density = operations.density(graph); - test.assertEqual(density, 1, 'Density of complete graph should be 1'); - } - }, - - noEdgesGraphDensity : function(){ - var graph = Viva.Graph.graph(), - operations = Viva.Graph.operations(); - - for (var i = 0; i < 10; ++i) { - graph.addNode(i); - } - - var density = operations.density(graph); - - test.assertEqual(density, 0, 'Density of graph with no edges should be 0'); - }, - - degreeCentralityOneEdge : function(){ - var graph = Viva.Graph.graph(), - cd; - graph.addLink(0, 1); - cd = Viva.Graph.centrality().degreeCentrality(graph); - - test.assertEqual(cd[0].value, 1, 'Unexpected node degree centrality'); - }, - - degreeCentralityCompleteGraph : function() { - var graph = Viva.Graph.generator().complete(6), - cd; - - cd = Viva.Graph.centrality().degreeCentrality(graph); - - test.assertEqual(cd[0].value, 5, 'Unexpected complete graph node centrality'); - } - }; -}; \ No newline at end of file +var test = require('tap').test; +var Viva = require('../dist/vivagraph.js'); + +test('twoNodeGraphDensity', function(t) { + var graph = Viva.Graph.graph(), + operations = Viva.Graph.operations(); + + graph.addLink(1, 2); + + var density = operations.density(graph); + + t.equals(density, 1, 'Density of two node graph should be 1'); + t.end(); +}); + +test('completeGraphDensity', function(t) { + var operations = Viva.Graph.operations(); + + for (var i = 2; i < 10; ++i) { + var graph = Viva.Graph.generator().complete(i); + var density = operations.density(graph); + t.equals(density, 1, 'Density of complete graph should be 1'); + } + t.end(); +}); + +test('noEdgesGraphDensity', function(t) { + var graph = Viva.Graph.graph(), + operations = Viva.Graph.operations(); + + for (var i = 0; i < 10; ++i) { + graph.addNode(i); + } + + var density = operations.density(graph); + + t.equals(density, 0, 'Density of graph with no edges should be 0'); + t.end(); +}); + +test('degreeCentralityOneEdge', function(t) { + var graph = Viva.Graph.graph(), + cd; + graph.addLink(0, 1); + cd = Viva.Graph.centrality().degreeCentrality(graph); + + t.equals(cd[0].value, 1, 'Unexpected node degree centrality'); + t.end(); +}); + +test('degreeCentralityCompleteGraph', function(t) { + var graph = Viva.Graph.generator().complete(6), + cd; + + cd = Viva.Graph.centrality().degreeCentrality(graph); + + t.equals(cd[0].value, 5, 'Unexpected complete graph node centrality'); + t.end(); +}); diff --git a/unit_tests/test_graphSerialization.js b/unit_tests/test_graphSerialization.js index be33a35..3a52921 100644 --- a/unit_tests/test_graphSerialization.js +++ b/unit_tests/test_graphSerialization.js @@ -1,77 +1,96 @@ -/*global Viva, console*/ - -var test_GraphSerialization = function(test){ - var assertGraphsAreSame = function(expected, actual) { - test.assertEqual(expected.getNodesCount(), actual.getNodesCount(), 'Number of nodes does not match for graph: ' + expected.Name); - test.assertEqual(expected.getLinksCount(), actual.getLinksCount(), 'Number of links does not match for graph: ' + expected.Name); - - expected.forEachNode(function(node){ - test.assert(actual.getNode(node.id), 'Actual graph is missing node with id: ' + node.id); - }); - - expected.forEachLink(function(link){ - test.assert(actual.hasLink(link.fromId, link.toId), 'Actual graph is missing link from ' + link.fromId + ' to ' + link.toId); - }); - }; - - return { - jsonStoreLoadProduceSameResult : function() { - var s = Viva.Graph.serializer(), - generator = Viva.Graph.generator(), - testGraphs = [ - generator.path(10), - generator.complete(10), - generator.grid(10, 10), - generator.completeBipartite(10, 10), - generator.circularLadder(10), - generator.randomNoLinks(10) - ]; - - - for(var i = 0; i < testGraphs.length; ++i) { - var testGraph = testGraphs[i], - storedGraph = s.storeToJSON(testGraph), - loadedGraph = s.loadFromJSON(storedGraph); - - assertGraphsAreSame(testGraph, loadedGraph); - } - }, - - jsonStoreWithCustomTransformer : function(){ - var s = Viva.Graph.serializer(), - g = Viva.Graph.graph(); - - g.addNode(1, 'Custom data'); - g.addLink(1, 2, 'Custom link data'); - - var json = s.storeToJSON(g, - function(node) { return [node.id, node.data]; }, // custom node serializer. transofrm it to array - function(link) { return [link.fromId, link.toId, link.data]; }), - parsedGraph; - - parsedGraph = JSON.parse(json); - - test.assertEqual(parsedGraph.nodes[0][0], 1, 'First node id should be stored in array'); - test.assertEqual(parsedGraph.nodes[0][1], 'Custom data', 'First node id should be stored in array'); - test.assertEqual(parsedGraph.links[0][1], 2, 'To link id should be stored in array'); - }, - - jsonLoadWithCustomTransform : function() { - var s = Viva.Graph.serializer(), - g = Viva.Graph.graph(); - - g.addNode(1, 'Custom data'); - g.addLink(1, 2, 'Custom link data'); - - var json = s.storeToJSON(g, - function(node) { return [node.id, node.data]; }, // custom node serializer. transofrm it to array - function(link) { return [link.fromId, link.toId, link.data]; }); - - var parsed = s.loadFromJSON(json, - function(node) { return { id : node[0], data : node[1]}; }, - function(link) { return { fromId : link[0], toId : link[1], data : link[2]}; } ); - - assertGraphsAreSame(g, parsed); - } - }; -}; \ No newline at end of file +var test = require('tap').test; +var Viva = require('../dist/vivagraph.js'); + +test('jsonStoreLoadProduceSameResult', function(t) { + var s = Viva.Graph.serializer(), + generator = Viva.Graph.generator(), + testGraphs = [ + generator.path(10), + generator.complete(10), + generator.grid(10, 10), + generator.completeBipartite(10, 10), + generator.circularLadder(10), + generator.randomNoLinks(10) + ]; + + + for (var i = 0; i < testGraphs.length; ++i) { + var testGraph = testGraphs[i], + storedGraph = s.storeToJSON(testGraph), + loadedGraph = s.loadFromJSON(storedGraph); + + assertGraphsAreSame(testGraph, loadedGraph, t); + } + t.end(); +}); + +test('jsonStoreWithCustomTransformer', function(t) { + var s = Viva.Graph.serializer(), + g = Viva.Graph.graph(); + + g.addNode(1, 'Custom data'); + g.addLink(1, 2, 'Custom link data'); + + var json = s.storeToJSON(g, + function(node) { + return [node.id, node.data]; + }, // custom node serializer. transofrm it to array + function(link) { + return [link.fromId, link.toId, link.data]; + }), + parsedGraph; + + parsedGraph = JSON.parse(json); + + t.equals(parsedGraph.nodes[0][0], 1, 'First node id should be stored in array'); + t.equals(parsedGraph.nodes[0][1], 'Custom data', 'First node id should be stored in array'); + t.equals(parsedGraph.links[0][1], 2, 'To link id should be stored in array'); + t.end(); +}); + +test('jsonLoadWithCustomTransform', function(t) { + var s = Viva.Graph.serializer(), + g = Viva.Graph.graph(); + + g.addNode(1, 'Custom data'); + g.addLink(1, 2, 'Custom link data'); + + var json = s.storeToJSON(g, + function(node) { + return [node.id, node.data]; + }, // custom node serializer. transofrm it to array + function(link) { + return [link.fromId, link.toId, link.data]; + }); + + var parsed = s.loadFromJSON(json, + function(node) { + return { + id: node[0], + data: node[1] + }; + }, + function(link) { + return { + fromId: link[0], + toId: link[1], + data: link[2] + }; + }); + + assertGraphsAreSame(g, parsed, t); + t.end(); +}); + +function assertGraphsAreSame(expected, actual,t) { + t.equals(expected.getNodesCount(), actual.getNodesCount(), 'Number of nodes does not match for graph: ' + expected.Name); + t.equals(expected.getLinksCount(), actual.getLinksCount(), 'Number of links does not match for graph: ' + expected.Name); + + expected.forEachNode(function(node) { + t.ok(actual.getNode(node.id), 'Actual graph is missing node with id: ' + node.id); + }); + + expected.forEachLink(function(link) { + t.ok(actual.hasLink(link.fromId, link.toId), 'Actual graph is missing link from ' + link.fromId + ' to ' + link.toId); + }); +} diff --git a/unit_tests/testing.js b/unit_tests/testing.js deleted file mode 100644 index 55cf6db..0000000 --- a/unit_tests/testing.js +++ /dev/null @@ -1,110 +0,0 @@ -/** - * @fileOverview Contains simple testing framework. - * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com - */ - -// TODO: I have to learn more about existing unit test frameworks in JS. -// But I'm too lazy at the moment so I wrote this simple micro framework - -/*global Viva, console */ - -var Viva = Viva || {}; - -Viva.testing = function(context){ - 'use strict'; - - var isTestCategoryName = function(propertyName){ - return propertyName && propertyName.indexOf('test_') === 0; - }, - - getAllCategoryNamesFromContext = function(){ - var categoryNames = [], - key; - - for(key in context){ - if (context.hasOwnProperty(key) && isTestCategoryName(key)) { - categoryNames.push(key); - } - } - - return categoryNames; - }, - - framework = { - log : function(level, message) { - console.log(message); - - var out = document.getElementById('output'), - domRecord; - - if (!out){ - out = document.createElement('div'); - out.id = 'output'; - document.body.appendChild(out); - } - - domRecord = document.createElement('div'); - domRecord.className = level; - domRecord.innerHTML = message; - - if (level === 'info') { - out.appendChild(document.createElement('br')); - } - - out.appendChild(domRecord); - }, - - assert : function(expression, message) { - if (!expression) { - throw message; - } - }, - - assertEqual : function(actual, expected, message) { - if (actual !== expected){ - throw message + '. Actual: ' + actual + '; expected: ' + expected; - } - }, - - assertFail : function(message){ - throw message; - }, - - run : function(testName, testFunction) { - framework.log('info', " * " + testName + '...', 3); - try{ - testFunction(); - framework.log('success', 'Success'); - } catch (e){ - framework.log('fail', 'FAILED: ' + e); - } - }, - - runAll : function(){ - var categoryNames = getAllCategoryNamesFromContext(), - i, categoryName, shortName, tests, testName; - framework.log('info', 'Running all tests'); - - for(i = 0; i < categoryNames.length; i += 1) { - categoryName = categoryNames[i]; - shortName = categoryName.match(/.+_(.+)/); - tests = context[categoryName](framework); - - shortName = (shortName && shortName[1]) || categoryName; - - framework.log('info', 'Running ' + shortName + ' category'); - - for(testName in tests) { - if (tests.hasOwnProperty(testName)){ - framework.run(testName, tests[testName]); - } - } - } - - framework.log('info', 'Done'); - } - }; - - return framework; -}; From c0b2f1f5529ef5320a0b2cbfa168b80736a078f9 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 28 Dec 2014 11:08:23 -0800 Subject: [PATCH 112/276] Removed redundant file name part --- unit_tests/{test_constantLayout.js => constantLayout.js} | 0 unit_tests/{test_forceBasedLayout.js => forceBasedLayout.js} | 0 unit_tests/{test_graphCommunity.js => graphCommunity.js} | 0 unit_tests/{test_graphConstructions.js => graphConstructions.js} | 0 unit_tests/{test_graphOperations.js => graphOperations.js} | 0 unit_tests/{test_graphSerialization.js => graphSerialization.js} | 0 unit_tests/{test_Utils.js => utils.js} | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename unit_tests/{test_constantLayout.js => constantLayout.js} (100%) rename unit_tests/{test_forceBasedLayout.js => forceBasedLayout.js} (100%) rename unit_tests/{test_graphCommunity.js => graphCommunity.js} (100%) rename unit_tests/{test_graphConstructions.js => graphConstructions.js} (100%) rename unit_tests/{test_graphOperations.js => graphOperations.js} (100%) rename unit_tests/{test_graphSerialization.js => graphSerialization.js} (100%) rename unit_tests/{test_Utils.js => utils.js} (100%) diff --git a/unit_tests/test_constantLayout.js b/unit_tests/constantLayout.js similarity index 100% rename from unit_tests/test_constantLayout.js rename to unit_tests/constantLayout.js diff --git a/unit_tests/test_forceBasedLayout.js b/unit_tests/forceBasedLayout.js similarity index 100% rename from unit_tests/test_forceBasedLayout.js rename to unit_tests/forceBasedLayout.js diff --git a/unit_tests/test_graphCommunity.js b/unit_tests/graphCommunity.js similarity index 100% rename from unit_tests/test_graphCommunity.js rename to unit_tests/graphCommunity.js diff --git a/unit_tests/test_graphConstructions.js b/unit_tests/graphConstructions.js similarity index 100% rename from unit_tests/test_graphConstructions.js rename to unit_tests/graphConstructions.js diff --git a/unit_tests/test_graphOperations.js b/unit_tests/graphOperations.js similarity index 100% rename from unit_tests/test_graphOperations.js rename to unit_tests/graphOperations.js diff --git a/unit_tests/test_graphSerialization.js b/unit_tests/graphSerialization.js similarity index 100% rename from unit_tests/test_graphSerialization.js rename to unit_tests/graphSerialization.js diff --git a/unit_tests/test_Utils.js b/unit_tests/utils.js similarity index 100% rename from unit_tests/test_Utils.js rename to unit_tests/utils.js From 33c5ebb6f326936e18f4edbf8382651b327f2e6b Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 28 Dec 2014 11:09:57 -0800 Subject: [PATCH 113/276] Changed `unit_tests` to `tests` --- package.json | 2 +- {unit_tests => tests}/constantLayout.js | 0 {unit_tests => tests}/forceBasedLayout.js | 0 {unit_tests => tests}/graphCommunity.js | 0 {unit_tests => tests}/graphConstructions.js | 0 {unit_tests => tests}/graphOperations.js | 0 {unit_tests => tests}/graphSerialization.js | 0 {unit_tests => tests}/perf/perf_test.js | 0 {unit_tests => tests}/perf/switch_graphs.js | 0 {unit_tests => tests}/utils.js | 0 10 files changed, 1 insertion(+), 1 deletion(-) rename {unit_tests => tests}/constantLayout.js (100%) rename {unit_tests => tests}/forceBasedLayout.js (100%) rename {unit_tests => tests}/graphCommunity.js (100%) rename {unit_tests => tests}/graphConstructions.js (100%) rename {unit_tests => tests}/graphOperations.js (100%) rename {unit_tests => tests}/graphSerialization.js (100%) rename {unit_tests => tests}/perf/perf_test.js (100%) rename {unit_tests => tests}/perf/switch_graphs.js (100%) rename {unit_tests => tests}/utils.js (100%) diff --git a/package.json b/package.json index 1b4bacf..8fdb556 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ }, "scripts": { "start": "gulp", - "test": "tap unit_tests/*.js" + "test": "tap tests/*.js" }, "repository": { "type": "git", diff --git a/unit_tests/constantLayout.js b/tests/constantLayout.js similarity index 100% rename from unit_tests/constantLayout.js rename to tests/constantLayout.js diff --git a/unit_tests/forceBasedLayout.js b/tests/forceBasedLayout.js similarity index 100% rename from unit_tests/forceBasedLayout.js rename to tests/forceBasedLayout.js diff --git a/unit_tests/graphCommunity.js b/tests/graphCommunity.js similarity index 100% rename from unit_tests/graphCommunity.js rename to tests/graphCommunity.js diff --git a/unit_tests/graphConstructions.js b/tests/graphConstructions.js similarity index 100% rename from unit_tests/graphConstructions.js rename to tests/graphConstructions.js diff --git a/unit_tests/graphOperations.js b/tests/graphOperations.js similarity index 100% rename from unit_tests/graphOperations.js rename to tests/graphOperations.js diff --git a/unit_tests/graphSerialization.js b/tests/graphSerialization.js similarity index 100% rename from unit_tests/graphSerialization.js rename to tests/graphSerialization.js diff --git a/unit_tests/perf/perf_test.js b/tests/perf/perf_test.js similarity index 100% rename from unit_tests/perf/perf_test.js rename to tests/perf/perf_test.js diff --git a/unit_tests/perf/switch_graphs.js b/tests/perf/switch_graphs.js similarity index 100% rename from unit_tests/perf/switch_graphs.js rename to tests/perf/switch_graphs.js diff --git a/unit_tests/utils.js b/tests/utils.js similarity index 100% rename from unit_tests/utils.js rename to tests/utils.js From abe86bc7ebc3129e654f431dc1c908b3a5eaaaac Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 28 Dec 2014 11:12:41 -0800 Subject: [PATCH 114/276] `tests` -> `test` --- package.json | 2 +- {tests => test}/constantLayout.js | 0 {tests => test}/forceBasedLayout.js | 0 {tests => test}/graphCommunity.js | 0 {tests => test}/graphConstructions.js | 0 {tests => test}/graphOperations.js | 0 {tests => test}/graphSerialization.js | 0 {tests => test}/perf/perf_test.js | 0 {tests => test}/perf/switch_graphs.js | 0 {tests => test}/utils.js | 0 10 files changed, 1 insertion(+), 1 deletion(-) rename {tests => test}/constantLayout.js (100%) rename {tests => test}/forceBasedLayout.js (100%) rename {tests => test}/graphCommunity.js (100%) rename {tests => test}/graphConstructions.js (100%) rename {tests => test}/graphOperations.js (100%) rename {tests => test}/graphSerialization.js (100%) rename {tests => test}/perf/perf_test.js (100%) rename {tests => test}/perf/switch_graphs.js (100%) rename {tests => test}/utils.js (100%) diff --git a/package.json b/package.json index 8fdb556..9cf3d18 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ }, "scripts": { "start": "gulp", - "test": "tap tests/*.js" + "test": "tap test/*.js" }, "repository": { "type": "git", diff --git a/tests/constantLayout.js b/test/constantLayout.js similarity index 100% rename from tests/constantLayout.js rename to test/constantLayout.js diff --git a/tests/forceBasedLayout.js b/test/forceBasedLayout.js similarity index 100% rename from tests/forceBasedLayout.js rename to test/forceBasedLayout.js diff --git a/tests/graphCommunity.js b/test/graphCommunity.js similarity index 100% rename from tests/graphCommunity.js rename to test/graphCommunity.js diff --git a/tests/graphConstructions.js b/test/graphConstructions.js similarity index 100% rename from tests/graphConstructions.js rename to test/graphConstructions.js diff --git a/tests/graphOperations.js b/test/graphOperations.js similarity index 100% rename from tests/graphOperations.js rename to test/graphOperations.js diff --git a/tests/graphSerialization.js b/test/graphSerialization.js similarity index 100% rename from tests/graphSerialization.js rename to test/graphSerialization.js diff --git a/tests/perf/perf_test.js b/test/perf/perf_test.js similarity index 100% rename from tests/perf/perf_test.js rename to test/perf/perf_test.js diff --git a/tests/perf/switch_graphs.js b/test/perf/switch_graphs.js similarity index 100% rename from tests/perf/switch_graphs.js rename to test/perf/switch_graphs.js diff --git a/tests/utils.js b/test/utils.js similarity index 100% rename from tests/utils.js rename to test/utils.js From eeed1f09dcf64f79fa257a1e0904de5659f312cb Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 28 Dec 2014 11:22:55 -0800 Subject: [PATCH 115/276] Ignore npm-debug --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 2867fd8..180ddfc 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ *.swp *.launch .DS_Store -node_modules \ No newline at end of file +node_modules +npm-debug.log From 0407f0776c9020484056cf2b7888ddc6d1f4703e Mon Sep 17 00:00:00 2001 From: Andrei Kashcha Date: Tue, 30 Dec 2014 19:24:10 -0800 Subject: [PATCH 116/276] Removed redundant links --- README.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/README.md b/README.md index b5b903d..3d75bbf 100644 --- a/README.md +++ b/README.md @@ -179,9 +179,4 @@ I need your feedback ---------------------------------------------------- Disclaimer: I wrote this library to learn JavaScript. By no means I pretend to be an expert in the language and chosen approach to design may not be the optimal. I would love to hear your feedback and suggestions. -Though I implemented this library from scratch, I went through many existing libraries to pick the best (at my view) out of them. If you are evaluating libraries for your project make sure to check them out as well: - -* [Dracula Graph Library](https://github.com/strathausen/dracula) - written by [Johann Philipp Strathausen](https://github.com/strathausen) and uses [Raphaël](http://raphaeljs.com/) library to render graphs. Has very simple API. -* [D3](http://mbostock.github.com/d3/ex/force.html) - one of the best data visualization library in JavaScript world. From [Mike Bostock](https://github.com/mbostock). - My goal is to create highly performant javascript library, which serves in the field of graph drawing. To certain extent I achieved it. But I have no doubt there is much more to improve here. From 55c0a808ac55101719c6bfb1d655cd5e0b5391c7 Mon Sep 17 00:00:00 2001 From: anvaka Date: Fri, 9 Jan 2015 00:32:22 -0800 Subject: [PATCH 117/276] Moved webgl to commonjs modules Preserving API. It's clunky, but will do refactoring as a next step --- gulpfile.js | 27 +- package.json | 8 +- src/Core/graph.js | 387 ----------------------------- src/Input/dragndrop.js | 2 + src/Utils/documentEvents.js | 32 +++ src/WebGL/parseColor.js | 22 ++ src/WebGL/texture.js | 11 + src/WebGL/webgl.js | 6 +- src/WebGL/webglAtlas.js | 181 ++++++++++++++ src/WebGL/webglImage.js | 30 +++ src/WebGL/webglImageNodeProgram.js | 198 +-------------- src/WebGL/webglInputEvents.js | 13 +- src/WebGL/webglLine.js | 20 ++ src/WebGL/webglLinkProgram.js | 12 +- src/WebGL/webglNodeProgram.js | 10 +- src/WebGL/webglSquare.js | 24 ++ src/WebGL/webglUIModels.js | 101 -------- src/version.js | 3 +- src/viva.js | 32 +++ src/vivagraph.js | 9 - 20 files changed, 414 insertions(+), 714 deletions(-) delete mode 100644 src/Core/graph.js create mode 100644 src/Utils/documentEvents.js create mode 100644 src/WebGL/parseColor.js create mode 100644 src/WebGL/texture.js create mode 100644 src/WebGL/webglAtlas.js create mode 100644 src/WebGL/webglImage.js create mode 100644 src/WebGL/webglLine.js create mode 100644 src/WebGL/webglSquare.js delete mode 100644 src/WebGL/webglUIModels.js create mode 100644 src/viva.js delete mode 100644 src/vivagraph.js diff --git a/gulpfile.js b/gulpfile.js index 723cc27..4161024 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,15 +1,16 @@ var gulp = require('gulp'); -var concat = require('gulp-concat'); +var gutil = require('gulp-util'); +var buffer = require('vinyl-buffer'); +var source = require('vinyl-source-stream'); + var path = require('path'); var uglify = require('gulp-uglify'); var rename = require('gulp-rename'); var del = require('del'); var run = require('gulp-run'); -var files = getFiles(); - gulp.task('clean', clean); -gulp.task('build', concatenateFiles); +gulp.task('build', build); gulp.task('test', test); gulp.task('release', ['clean', 'build', 'test']); gulp.task('default', watch); @@ -26,20 +27,28 @@ function test() { new run.Command('npm test').exec(); } -function concatenateFiles() { - gulp.src(files) - .pipe(concat('vivagraph.js')) +function build() { + var bundler = require('browserify')('./src/viva.js', { + standalone: 'Viva' + }); + var bundle = bundler.bundle() + .on('error', showError); + + bundle.pipe(source('vivagraph.js')) + .pipe(buffer()) .pipe(gulp.dest('./dist/')) .pipe(rename('vivagraph.min.js')) .pipe(uglify()) .pipe(gulp.dest('./dist/')); + + function showError(err) { + gutil.log(gutil.colors.red('Failed to browserify'), gutil.colors.yellow(err.message)); + } } function getFiles() { // todo: this will be changed when we move to commonjs return [ // core - "vivagraph.js", - "version.js", "Utils/etc.js", "Utils/browserInfo.js", "Utils/indexOf.js", diff --git a/package.json b/package.json index 9cf3d18..08d71bb 100644 --- a/package.json +++ b/package.json @@ -20,14 +20,18 @@ "author": "Andrei Kashcha", "license": "BSD", "devDependencies": { + "browserify": "^8.0.3", "del": "^1.1.1", "gulp": "^3.8.10", - "gulp-concat": "^2.4.2", "gulp-rename": "^1.2.0", "gulp-uglify": "^1.0.2", + "gulp-run": "^1.6.5", + "gulp-util": "^3.0.2", + "vinyl-buffer": "^1.0.0", + "vinyl-source-stream": "^1.0.0", "tap": "^0.4.13" }, "dependencies": { - "gulp-run": "^1.6.5" + "ngraph.graph": "0.0.6" } } diff --git a/src/Core/graph.js b/src/Core/graph.js deleted file mode 100644 index 1ae401d..0000000 --- a/src/Core/graph.js +++ /dev/null @@ -1,387 +0,0 @@ -/** - * @fileOverview Contains definition of the core graph object. - * - * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka - */ - -/** - * @namespace Represents a graph data structure. - * - * @example - * var g = Viva.Graph.graph(); - * g.addNode(1); // g has one node. - * g.addLink(2, 3); // now g contains three nodes and one link. - * - */ -Viva.Graph.graph = function () { - - // Graph structure is maintained as dictionary of nodes - // and array of links. Each node has 'links' property which - // hold all links related to that node. And general links - // array is used to speed up all links enumeration. This is inefficient - // in terms of memory, but simplifies coding. Furthermore, the graph structure - // is isolated from outer world, and can be changed to adjacency matrix later. - - var nodes = (typeof Object.create === 'function') ? Object.create(null) : {}, - links = [], - // Hash of multi-edges. Used to track ids of edges between same nodes - multiEdges = {}, - nodesCount = 0, - suspendEvents = 0, - - // Accumulates all changes made during graph updates. - // Each change element contains: - // changeType - one of the strings: 'add', 'remove' or 'update'; - // node - if change is related to node this property is set to changed graph's node; - // link - if change is related to link this property is set to changed graph's link; - changes = [], - - fireGraphChanged = function (graph) { - // TODO: maybe we shall copy changes? - graph.fire('changed', changes); - }, - - // Enter, Exit modification allows bulk graph updates without firing events. - enterModification = function () { - suspendEvents += 1; - }, - - exitModification = function (graph) { - suspendEvents -= 1; - if (suspendEvents === 0 && changes.length > 0) { - fireGraphChanged(graph); - changes.length = 0; - } - }, - - recordNodeChange = function (node, changeType) { - // TODO: Could add changeType verification. - changes.push({node : node, changeType : changeType}); - }, - - recordLinkChange = function (link, changeType) { - // TODO: Could add change type verification; - changes.push({link : link, changeType : changeType}); - }; - - /** @scope Viva.Graph.graph */ - var graphPart = { - - /** - * Adds node to the graph. If node with given id already exists in the graph - * its data is extended with whatever comes in 'data' argument. - * - * @param nodeId the node's identifier. A string is preferred. - * @param [data] additional data for the node being added. If node already - * exists its data object is augmented with the new one. - * - * @return {node} The newly added node or node with given id if it already exists. - */ - addNode : function (nodeId, data) { - if (typeof nodeId === 'undefined') { - throw { - message: 'Invalid node identifier' - }; - } - - enterModification(); - - var node = this.getNode(nodeId); - if (!node) { - node = new Viva.Graph.Node(nodeId); - nodesCount++; - - recordNodeChange(node, 'add'); - } else { - recordNodeChange(node, 'update'); - } - - node.data = data; - - nodes[nodeId] = node; - - exitModification(this); - return node; - }, - - /** - * Adds a link to the graph. The function always create a new - * link between two nodes. If one of the nodes does not exists - * a new node is created. - * - * @param fromId link start node id; - * @param toId link end node id; - * @param [data] additional data to be set on the new link; - * - * @return {link} The newly created link - */ - addLink : function (fromId, toId, data) { - enterModification(); - - var fromNode = this.getNode(fromId) || this.addNode(fromId); - var toNode = this.getNode(toId) || this.addNode(toId); - - var linkId = fromId.toString() +'👉 ' + toId.toString(); - var isMultiEdge = multiEdges.hasOwnProperty(linkId); - if (isMultiEdge || this.hasLink(fromId, toId)) { - if (!isMultiEdge) { - multiEdges[linkId] = 0; - } - linkId += '@' + (++multiEdges[linkId]); - } - - var link = new Viva.Graph.Link(fromId, toId, data, linkId); - - links.push(link); - - // TODO: this is not cool. On large graphs potentially would consume more memory. - fromNode.links.push(link); - toNode.links.push(link); - - recordLinkChange(link, 'add'); - - exitModification(this); - - return link; - }, - - /** - * Removes link from the graph. If link does not exist does nothing. - * - * @param link - object returned by addLink() or getLinks() methods. - * - * @returns true if link was removed; false otherwise. - */ - removeLink : function (link) { - if (!link) { return false; } - var idx = Viva.Graph.Utils.indexOfElementInArray(link, links); - if (idx < 0) { return false; } - - enterModification(); - - links.splice(idx, 1); - - var fromNode = this.getNode(link.fromId); - var toNode = this.getNode(link.toId); - - if (fromNode) { - idx = Viva.Graph.Utils.indexOfElementInArray(link, fromNode.links); - if (idx >= 0) { - fromNode.links.splice(idx, 1); - } - } - - if (toNode) { - idx = Viva.Graph.Utils.indexOfElementInArray(link, toNode.links); - if (idx >= 0) { - toNode.links.splice(idx, 1); - } - } - - recordLinkChange(link, 'remove'); - - exitModification(this); - - return true; - }, - - /** - * Removes node with given id from the graph. If node does not exist in the graph - * does nothing. - * - * @param nodeId node's identifier passed to addNode() function. - * - * @returns true if node was removed; false otherwise. - */ - removeNode: function (nodeId) { - var node = this.getNode(nodeId); - if (!node) { return false; } - - enterModification(); - - while (node.links.length) { - var link = node.links[0]; - this.removeLink(link); - } - - nodes[nodeId] = null; - delete nodes[nodeId]; - nodesCount--; - - recordNodeChange(node, 'remove'); - - exitModification(this); - }, - - /** - * Gets node with given identifier. If node does not exist undefined value is returned. - * - * @param nodeId requested node identifier; - * - * @return {node} in with requested identifier or undefined if no such node exists. - */ - getNode : function (nodeId) { - return nodes[nodeId]; - }, - - /** - * Gets number of nodes in this graph. - * - * @return number of nodes in the graph. - */ - getNodesCount : function () { - return nodesCount; - }, - - /** - * Gets total number of links in the graph. - */ - getLinksCount : function () { - return links.length; - }, - - /** - * Gets all links (inbound and outbound) from the node with given id. - * If node with given id is not found null is returned. - * - * @param nodeId requested node identifier. - * - * @return Array of links from and to requested node if such node exists; - * otherwise null is returned. - */ - getLinks : function (nodeId) { - var node = this.getNode(nodeId); - return node ? node.links : null; - }, - - /** - * Invokes callback on each node of the graph. - * - * @param {Function(node)} callback Function to be invoked. The function - * is passed one argument: visited node. - */ - forEachNode : function (callback) { - if (typeof callback !== 'function') { - return; - } - var node; - - // TODO: could it be faster for nodes iteration if we had indexed access? - // I.e. use array + 'for' iterator instead of dictionary + 'for .. in'? - for (node in nodes) { - if (callback(nodes[node])) { - return; // client doesn't want to proceed. - } - } - }, - - /** - * Invokes callback on every linked (adjacent) node to the given one. - * - * @param nodeId Identifier of the requested node. - * @param {Function(node, link)} callback Function to be called on all linked nodes. - * The function is passed two parameters: adjacent node and link object itself. - * @param oriented if true graph treated as oriented. - */ - forEachLinkedNode : function (nodeId, callback, oriented) { - var node = this.getNode(nodeId), - i, - link, - linkedNodeId; - - if (node && node.links && typeof callback === 'function') { - // Extracted orientation check out of the loop to increase performance - if (oriented) { - for (i = 0; i < node.links.length; ++i) { - link = node.links[i]; - if (link.fromId === nodeId) { - callback(nodes[link.toId], link); - } - } - } else { - for (i = 0; i < node.links.length; ++i) { - link = node.links[i]; - linkedNodeId = link.fromId === nodeId ? link.toId : link.fromId; - - callback(nodes[linkedNodeId], link); - } - } - } - }, - - /** - * Enumerates all links in the graph - * - * @param {Function(link)} callback Function to be called on all links in the graph. - * The function is passed one parameter: graph's link object. - * - * Link object contains at least the following fields: - * fromId - node id where link starts; - * toId - node id where link ends, - * data - additional data passed to graph.addLink() method. - */ - forEachLink : function (callback) { - var i, length; - if (typeof callback === 'function') { - for (i = 0, length = links.length; i < length; ++i) { - callback(links[i]); - } - } - }, - - /** - * Suspend all notifications about graph changes until - * endUpdate is called. - */ - beginUpdate : function () { - enterModification(); - }, - - /** - * Resumes all notifications about graph changes and fires - * graph 'changed' event in case there are any pending changes. - */ - endUpdate : function () { - exitModification(this); - }, - - /** - * Removes all nodes and links from the graph. - */ - clear : function () { - var that = this; - that.beginUpdate(); - that.forEachNode(function (node) { that.removeNode(node.id); }); - that.endUpdate(); - }, - - /** - * Detects whether there is a link between two nodes. - * Operation complexity is O(n) where n - number of links of a node. - * - * @returns link if there is one. null otherwise. - */ - hasLink : function (fromNodeId, toNodeId) { - // TODO: Use adjacency matrix to speed up this operation. - var node = this.getNode(fromNodeId), - i; - if (!node) { - return null; - } - - for (i = 0; i < node.links.length; ++i) { - var link = node.links[i]; - if (link.fromId === fromNodeId && link.toId === toNodeId) { - return link; - } - } - - return null; // no link. - } - }; - - // Let graph fire events before we return it to the caller. - Viva.Graph.Utils.events(graphPart).extend(); - - return graphPart; -}; diff --git a/src/Input/dragndrop.js b/src/Input/dragndrop.js index 184df18..c101168 100644 --- a/src/Input/dragndrop.js +++ b/src/Input/dragndrop.js @@ -2,6 +2,8 @@ * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ +// TODO: Replace documentEvents with commonjs modulek + Viva.Graph.Utils = Viva.Graph.Utils || {}; // TODO: Move to input namespace diff --git a/src/Utils/documentEvents.js b/src/Utils/documentEvents.js new file mode 100644 index 0000000..743855e --- /dev/null +++ b/src/Utils/documentEvents.js @@ -0,0 +1,32 @@ +var nullEvents = createNullEvents(); + +module.exports = createDocumentEvents(); + +function createDocumentEvents() { + if (typeof document === undefined) { + return nullEvents; + } + + return { + on: on, + off: off + }; +} + +function on(eventName, handler) { + document.addEventListener(eventName, handler); +} + +function off(eventName, handler) { + document.removeEventListener(eventName, handler); +} + +function createNullEvents() { + return { + on: noop, + off: noop, + stop: noop + }; +} + +function noop() { } diff --git a/src/WebGL/parseColor.js b/src/WebGL/parseColor.js new file mode 100644 index 0000000..5a83883 --- /dev/null +++ b/src/WebGL/parseColor.js @@ -0,0 +1,22 @@ +module.exports = parseColor; + +function parseColor(color) { + var parsedColor = 0x009ee8ff; + + if (typeof color === 'string' && color) { + if (color.length === 4) { // #rgb + color = color.replace(/([^#])/g, '$1$1'); // duplicate each letter except first #. + } + if (color.length === 9) { // #rrggbbaa + parsedColor = parseInt(color.substr(1), 16); + } else if (color.length === 7) { // or #rrggbb. + parsedColor = (parseInt(color.substr(1), 16) << 8) | 0xff; + } else { + throw 'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: ' + color; + } + } else if (typeof color === 'number') { + parsedColor = color; + } + + return parsedColor; +} diff --git a/src/WebGL/texture.js b/src/WebGL/texture.js new file mode 100644 index 0000000..be26a74 --- /dev/null +++ b/src/WebGL/texture.js @@ -0,0 +1,11 @@ +module.exports = Texture; + +/** + * Single texture in the webglAtlas. + */ +function Texture(size) { + this.canvas = window.document.createElement("canvas"); + this.ctx = this.canvas.getContext("2d"); + this.isDirty = false; + this.canvas.width = this.canvas.height = size; +} diff --git a/src/WebGL/webgl.js b/src/WebGL/webgl.js index 80b6cfb..6fadbaa 100644 --- a/src/WebGL/webgl.js +++ b/src/WebGL/webgl.js @@ -4,7 +4,9 @@ * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com */ -Viva.Graph.webgl = function (gl) { +module.exports = webgl; + +function webgl(gl) { var createShader = function (shaderText, type) { var shader = gl.createShader(type); gl.shaderSource(shader, shaderText); @@ -97,4 +99,4 @@ Viva.Graph.webgl = function (gl) { context : gl }; -}; +} diff --git a/src/WebGL/webglAtlas.js b/src/WebGL/webglAtlas.js new file mode 100644 index 0000000..d9ebca2 --- /dev/null +++ b/src/WebGL/webglAtlas.js @@ -0,0 +1,181 @@ +var Texture = require('./texture.js'); + +module.exports = webglAtlas; + +/** + * My naive implementation of textures atlas. It allows clients to load + * multiple images into atlas and get canvas representing all of them. + * + * @param tilesPerTexture - indicates how many images can be loaded to one + * texture of the atlas. If number of loaded images exceeds this + * parameter a new canvas will be created. + */ +function webglAtlas(tilesPerTexture) { + var tilesPerRow = Math.sqrt(tilesPerTexture || 1024) << 0, + tileSize = tilesPerRow, + lastLoadedIdx = 1, + loadedImages = {}, + dirtyTimeoutId, + skipedDirty = 0, + textures = [], + trackedUrls = [], + that, + + isPowerOf2 = function (n) { + return (n & (n - 1)) === 0; + }, + createTexture = function () { + var texture = new Texture(tilesPerRow * tileSize); + textures.push(texture); + }, + getTileCoordinates = function (absolutePosition) { + var textureNumber = (absolutePosition / tilesPerTexture) << 0, + localTileNumber = (absolutePosition % tilesPerTexture), + row = (localTileNumber / tilesPerRow) << 0, + col = (localTileNumber % tilesPerRow); + + return {textureNumber : textureNumber, row : row, col: col}; + }, + markDirtyNow = function () { + that.isDirty = true; + skipedDirty = 0; + dirtyTimeoutId = null; + }, + markDirty = function () { + // delay this call, since it results in texture reload + if (dirtyTimeoutId) { + window.clearTimeout(dirtyTimeoutId); + skipedDirty += 1; + dirtyTimeoutId = null; + } + + if (skipedDirty > 10) { + markDirtyNow(); + } else { + dirtyTimeoutId = window.setTimeout(markDirtyNow, 400); + } + }, + + copy = function (from, to) { + var fromCanvas = textures[from.textureNumber].canvas, + toCtx = textures[to.textureNumber].ctx, + x = to.col * tileSize, + y = to.row * tileSize; + + toCtx.drawImage(fromCanvas, from.col * tileSize, from.row * tileSize, tileSize, tileSize, x, y, tileSize, tileSize); + textures[from.textureNumber].isDirty = true; + textures[to.textureNumber].isDirty = true; + }, + + drawAt = function (tileNumber, img, callback) { + var tilePosition = getTileCoordinates(tileNumber), + coordinates = { offset : tileNumber }; + + if (tilePosition.textureNumber >= textures.length) { + createTexture(); + } + var currentTexture = textures[tilePosition.textureNumber]; + + currentTexture.ctx.drawImage(img, tilePosition.col * tileSize, tilePosition.row * tileSize, tileSize, tileSize); + trackedUrls[tileNumber] = img.src; + + loadedImages[img.src] = coordinates; + currentTexture.isDirty = true; + + callback(coordinates); + }; + + if (!isPowerOf2(tilesPerTexture)) { + throw "Tiles per texture should be power of two."; + } + + // this is the return object + that = { + /** + * indicates whether atlas has changed texture in it. If true then + * some of the textures has isDirty flag set as well. + */ + isDirty : false, + + /** + * Clears any signs of atlas changes. + */ + clearDirty : function () { + var i; + this.isDirty = false; + for (i = 0; i < textures.length; ++i) { + textures[i].isDirty = false; + } + }, + + /** + * Removes given url from collection of tiles in the atlas. + */ + remove : function (imgUrl) { + var coordinates = loadedImages[imgUrl]; + if (!coordinates) { return false; } + delete loadedImages[imgUrl]; + lastLoadedIdx -= 1; + + + if (lastLoadedIdx === coordinates.offset) { + return true; // Ignore if it's last image in the whole set. + } + + var tileToRemove = getTileCoordinates(coordinates.offset), + lastTileInSet = getTileCoordinates(lastLoadedIdx); + + copy(lastTileInSet, tileToRemove); + + var replacedOffset = loadedImages[trackedUrls[lastLoadedIdx]]; + replacedOffset.offset = coordinates.offset; + trackedUrls[coordinates.offset] = trackedUrls[lastLoadedIdx]; + + markDirty(); + return true; + }, + + /** + * Gets all textures in the atlas. + */ + getTextures : function () { + return textures; // I trust you... + }, + + /** + * Gets coordinates of the given image in the atlas. Coordinates is an object: + * {offset : int } - where offset is an absolute position of the image in the + * atlas. + * + * Absolute means it can be larger than tilesPerTexture parameter, and in that + * case clients should get next texture in getTextures() collection. + */ + getCoordinates : function (imgUrl) { + return loadedImages[imgUrl]; + }, + + /** + * Asynchronously Loads the image to the atlas. Cross-domain security + * limitation applies. + */ + load : function (imgUrl, callback) { + if (loadedImages.hasOwnProperty(imgUrl)) { + callback(loadedImages[imgUrl]); + } else { + var img = new window.Image(), + imgId = lastLoadedIdx; + + lastLoadedIdx += 1; + img.crossOrigin = "anonymous"; + img.onload = function () { + markDirty(); + drawAt(imgId, img, callback); + }; + + img.src = imgUrl; + } + } + }; + + return that; +} diff --git a/src/WebGL/webglImage.js b/src/WebGL/webglImage.js new file mode 100644 index 0000000..bf1dc5e --- /dev/null +++ b/src/WebGL/webglImage.js @@ -0,0 +1,30 @@ +module.exports = webglImage; + +/** + * Represents a model for image. + */ +function webglImage(size, src) { + return { + /** + * Gets texture index where current image is placed. + */ + _texture : 0, + + /** + * Gets offset in the texture where current image is placed. + */ + _offset : 0, + + /** + * Gets size of the square with the image. + */ + size : typeof size === 'number' ? size : 32, + + /** + * Source of the image. If image is coming not from your domain + * certain origin restrictions applies. + * See http://www.khronos.org/registry/webgl/specs/latest/#4.2 for more details. + */ + src : src + }; +} diff --git a/src/WebGL/webglImageNodeProgram.js b/src/WebGL/webglImageNodeProgram.js index 0dab89e..0169ead 100644 --- a/src/WebGL/webglImageNodeProgram.js +++ b/src/WebGL/webglImageNodeProgram.js @@ -5,199 +5,17 @@ * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com */ -/** - * Single texture in the webglAtlas. - */ -Viva.Graph.View.Texture = function (size) { - this.canvas = window.document.createElement("canvas"); - this.ctx = this.canvas.getContext("2d"); - this.isDirty = false; - this.canvas.width = this.canvas.height = size; -}; - -/** - * My naive implementation of textures atlas. It allows clients to load - * multiple images into atlas and get canvas representing all of them. - * - * @param tilesPerTexture - indicates how many images can be loaded to one - * texture of the atlas. If number of loaded images exceeds this - * parameter a new canvas will be created. - */ -Viva.Graph.View.webglAtlas = function (tilesPerTexture) { - var tilesPerRow = Math.sqrt(tilesPerTexture || 1024) << 0, - tileSize = tilesPerRow, - lastLoadedIdx = 1, - loadedImages = {}, - dirtyTimeoutId, - skipedDirty = 0, - textures = [], - trackedUrls = [], - that, - - isPowerOf2 = function (n) { - return (n & (n - 1)) === 0; - }, - createTexture = function () { - var texture = new Viva.Graph.View.Texture(tilesPerRow * tileSize); - textures.push(texture); - }, - getTileCoordinates = function (absolutePosition) { - var textureNumber = (absolutePosition / tilesPerTexture) << 0, - localTileNumber = (absolutePosition % tilesPerTexture), - row = (localTileNumber / tilesPerRow) << 0, - col = (localTileNumber % tilesPerRow); - - return {textureNumber : textureNumber, row : row, col: col}; - }, - markDirtyNow = function () { - that.isDirty = true; - skipedDirty = 0; - dirtyTimeoutId = null; - }, - markDirty = function () { - // delay this call, since it results in texture reload - if (dirtyTimeoutId) { - window.clearTimeout(dirtyTimeoutId); - skipedDirty += 1; - dirtyTimeoutId = null; - } - - if (skipedDirty > 10) { - markDirtyNow(); - } else { - dirtyTimeoutId = window.setTimeout(markDirtyNow, 400); - } - }, - - copy = function (from, to) { - var fromCanvas = textures[from.textureNumber].canvas, - toCtx = textures[to.textureNumber].ctx, - x = to.col * tileSize, - y = to.row * tileSize; - - toCtx.drawImage(fromCanvas, from.col * tileSize, from.row * tileSize, tileSize, tileSize, x, y, tileSize, tileSize); - textures[from.textureNumber].isDirty = true; - textures[to.textureNumber].isDirty = true; - }, - - drawAt = function (tileNumber, img, callback) { - var tilePosition = getTileCoordinates(tileNumber), - coordinates = { offset : tileNumber }; - - if (tilePosition.textureNumber >= textures.length) { - createTexture(); - } - var currentTexture = textures[tilePosition.textureNumber]; - - currentTexture.ctx.drawImage(img, tilePosition.col * tileSize, tilePosition.row * tileSize, tileSize, tileSize); - trackedUrls[tileNumber] = img.src; - - loadedImages[img.src] = coordinates; - currentTexture.isDirty = true; - - callback(coordinates); - }; - - if (!isPowerOf2(tilesPerTexture)) { - throw "Tiles per texture should be power of two."; - } - - // this is the return object - that = { - /** - * indicates whether atlas has changed texture in it. If true then - * some of the textures has isDirty flag set as well. - */ - isDirty : false, - - /** - * Clears any signs of atlas changes. - */ - clearDirty : function () { - var i; - this.isDirty = false; - for (i = 0; i < textures.length; ++i) { - textures[i].isDirty = false; - } - }, - - /** - * Removes given url from collection of tiles in the atlas. - */ - remove : function (imgUrl) { - var coordinates = loadedImages[imgUrl]; - if (!coordinates) { return false; } - delete loadedImages[imgUrl]; - lastLoadedIdx -= 1; - - - if (lastLoadedIdx === coordinates.offset) { - return true; // Ignore if it's last image in the whole set. - } - - var tileToRemove = getTileCoordinates(coordinates.offset), - lastTileInSet = getTileCoordinates(lastLoadedIdx); - - copy(lastTileInSet, tileToRemove); - - var replacedOffset = loadedImages[trackedUrls[lastLoadedIdx]]; - replacedOffset.offset = coordinates.offset; - trackedUrls[coordinates.offset] = trackedUrls[lastLoadedIdx]; - - markDirty(); - return true; - }, - - /** - * Gets all textures in the atlas. - */ - getTextures : function () { - return textures; // I trust you... - }, - - /** - * Gets coordinates of the given image in the atlas. Coordinates is an object: - * {offset : int } - where offset is an absolute position of the image in the - * atlas. - * - * Absolute means it can be larger than tilesPerTexture parameter, and in that - * case clients should get next texture in getTextures() collection. - */ - getCoordinates : function (imgUrl) { - return loadedImages[imgUrl]; - }, - - /** - * Asynchronously Loads the image to the atlas. Cross-domain security - * limitation applies. - */ - load : function (imgUrl, callback) { - if (loadedImages.hasOwnProperty(imgUrl)) { - callback(loadedImages[imgUrl]); - } else { - var img = new window.Image(), - imgId = lastLoadedIdx; - - lastLoadedIdx += 1; - img.crossOrigin = "anonymous"; - img.onload = function () { - markDirty(); - drawAt(imgId, img, callback); - }; - - img.src = imgUrl; - } - } - }; +var WebglAtlas = require('./webglAtlas.js'); +var glUtils = require('./webgl.js'); - return that; -}; +module.exports = webglImageNodeProgram; /** * Defines simple UI for nodes in webgl renderer. Each node is rendered as an image. */ -Viva.Graph.View.webglImageNodeProgram = function () { +function webglImageNodeProgram() { var ATTRIBUTES_PER_PRIMITIVE = 18, + // TODO: Use glslify for shaders nodesFS = [ "precision mediump float;", "varying vec4 color;", @@ -305,9 +123,9 @@ Viva.Graph.View.webglImageNodeProgram = function () { return { load : function (glContext) { gl = glContext; - utils = Viva.Graph.webgl(glContext); + utils = glUtils(glContext); - atlas = new Viva.Graph.View.webglAtlas(tilesPerTexture); + atlas = new WebglAtlas(tilesPerTexture); program = utils.createProgram(nodesVS, nodesFS); gl.useProgram(program); @@ -416,4 +234,4 @@ Viva.Graph.View.webglImageNodeProgram = function () { gl.drawArrays(gl.TRIANGLES, 0, nodesCount * 6); } }; -}; +} diff --git a/src/WebGL/webglInputEvents.js b/src/WebGL/webglInputEvents.js index 22d6eb0..1a692fa 100644 --- a/src/WebGL/webglInputEvents.js +++ b/src/WebGL/webglInputEvents.js @@ -1,9 +1,13 @@ +var documentEvents = require('../Utils/documentEvents.js'); + +module.exports = webglInputEvents; + /** * Monitors graph-related mouse input in webgl graphics and notifies subscribers. * * @param {Viva.Graph.View.webglGraphics} webglGraphics */ -Viva.Graph.webglInputEvents = function (webglGraphics) { +function webglInputEvents(webglGraphics) { if (webglGraphics.webglInputEvents) { // Don't listen twice, if we are already attached to this graphics: return webglGraphics.webglInputEvents; @@ -32,7 +36,6 @@ Viva.Graph.webglInputEvents = function (webglGraphics) { mouseMoveCallback = [], clickCallback = [], dblClickCallback = [], - documentEvents = Viva.Graph.Utils.events(window.document), prevSelectStart, boundRect, @@ -69,8 +72,8 @@ Viva.Graph.webglInputEvents = function (webglGraphics) { }, handleMouseUp = function () { - documentEvents.stop('mousemove', handleMouseMove); - documentEvents.stop('mouseup', handleMouseUp); + documentEvents.off('mousemove', handleMouseMove); + documentEvents.off('mouseup', handleMouseUp); }, updateBoundRect = function () { @@ -214,4 +217,4 @@ Viva.Graph.webglInputEvents = function (webglGraphics) { }; return webglGraphics.webglInputEvents; -}; +} diff --git a/src/WebGL/webglLine.js b/src/WebGL/webglLine.js new file mode 100644 index 0000000..9fbe352 --- /dev/null +++ b/src/WebGL/webglLine.js @@ -0,0 +1,20 @@ +var parseColor = require('./parseColor.js'); + +module.exports = webglLine; + +/** + * Defines a webgl line. This class has no rendering logic at all, + * it's just passed to corresponding shader and the shader should + * figure out how to render it. + * + * @see Viva.Graph.View.webglLinkShader.position + */ +function webglLine(color) { + return { + /** + * Gets or sets color of the line. If you set this property externally + * make sure it always come as integer of 0xRRGGBBAA format + */ + color: parseColor(color) + }; +} diff --git a/src/WebGL/webglLinkProgram.js b/src/WebGL/webglLinkProgram.js index a1dc438..cf23fad 100644 --- a/src/WebGL/webglLinkProgram.js +++ b/src/WebGL/webglLinkProgram.js @@ -1,14 +1,16 @@ /** * @fileOverview Defines a naive form of links for webglGraphics class. * This form allows to change color of links. - * - * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka **/ +var glUtils = require('./webgl.js'); + +module.exports = webglLinkProgram; + /** * Defines UI for links in webgl renderer. */ -Viva.Graph.View.webglLinkProgram = function () { +function webglLinkProgram() { var ATTRIBUTES_PER_PRIMITIVE = 6, // primitive is Line with two points. Each has x,y and color = 3 * 2 attributes. BYTES_PER_LINK = 2 * (2 * Float32Array.BYTES_PER_ELEMENT + Uint32Array.BYTES_PER_ELEMENT), // two nodes * (x, y + color) linksFS = [ @@ -68,7 +70,7 @@ Viva.Graph.View.webglLinkProgram = function () { return { load : function (glContext) { gl = glContext; - utils = Viva.Graph.webgl(glContext); + utils = glUtils(glContext); program = utils.createProgram(linksVS, linksFS); gl.useProgram(program); @@ -151,4 +153,4 @@ Viva.Graph.View.webglLinkProgram = function () { return frontLinkId; } }; -}; +} diff --git a/src/WebGL/webglNodeProgram.js b/src/WebGL/webglNodeProgram.js index 5162f19..8b1d66b 100644 --- a/src/WebGL/webglNodeProgram.js +++ b/src/WebGL/webglNodeProgram.js @@ -5,10 +5,14 @@ * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ +var glUtils = require('./webgl.js'); + +module.exports = webglNodeProgram; + /** * Defines simple UI for nodes in webgl renderer. Each node is rendered as square. Color and size can be changed. */ -Viva.Graph.View.webglNodeProgram = function () { +function webglNodeProgram() { var ATTRIBUTES_PER_PRIMITIVE = 4, // Primitive is point, x, y, size, color // x, y, z - floats, color = uint. BYTES_PER_NODE = 3 * Float32Array.BYTES_PER_ELEMENT + Uint32Array.BYTES_PER_ELEMENT, @@ -66,7 +70,7 @@ Viva.Graph.View.webglNodeProgram = function () { return { load : function (glContext) { gl = glContext; - utils = Viva.Graph.webgl(glContext); + utils = glUtils(glContext); program = utils.createProgram(nodesVS, nodesFS); gl.useProgram(program); @@ -139,4 +143,4 @@ Viva.Graph.View.webglNodeProgram = function () { gl.drawArrays(gl.POINTS, 0, nodesCount); } }; -}; +} diff --git a/src/WebGL/webglSquare.js b/src/WebGL/webglSquare.js new file mode 100644 index 0000000..abdeee5 --- /dev/null +++ b/src/WebGL/webglSquare.js @@ -0,0 +1,24 @@ +var parseColor = require('./parseColor.js'); + +module.exports = webglSquare; + +/** + * Can be used as a callback in the webglGraphics.node() function, to + * create a custom looking node. + * + * @param size - size of the node in pixels. + * @param color - color of the node in '#rrggbbaa' or '#rgb' format. + */ +function webglSquare(size, color) { + return { + /** + * Gets or sets size of the square side. + */ + size: typeof size === 'number' ? size : 10, + + /** + * Gets or sets color of the square. + */ + color: parseColor(color) + }; +} diff --git a/src/WebGL/webglUIModels.js b/src/WebGL/webglUIModels.js deleted file mode 100644 index 5cb35b2..0000000 --- a/src/WebGL/webglUIModels.js +++ /dev/null @@ -1,101 +0,0 @@ -/** - * @fileOverview Defines a model objects to represents graph rendering - * primitives in webglGraphics. - * - * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka - */ - -Viva.Graph.View.WebglUtils = function () { }; - -/** - * Parses various color strings and returns color value used in webgl shaders. - */ -Viva.Graph.View.WebglUtils.prototype.parseColor = function (color) { - var parsedColor = 0x009ee8ff; - - if (typeof color === 'string' && color) { - if (color.length === 4) { // #rgb - color = color.replace(/([^#])/g, '$1$1'); // duplicate each letter except first #. - } - if (color.length === 9) { // #rrggbbaa - parsedColor = parseInt(color.substr(1), 16); - } else if (color.length === 7) { // or #rrggbb. - parsedColor = (parseInt(color.substr(1), 16) << 8) | 0xff; - } else { - throw 'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: ' + color; - } - } else if (typeof color === 'number') { - parsedColor = color; - } - - return parsedColor; -}; - -Viva.Graph.View._webglUtil = new Viva.Graph.View.WebglUtils(); // reuse this instance internally. - -/** - * Defines a webgl line. This class has no rendering logic at all, - * it's just passed to corresponding shader and the shader should - * figure out how to render it. - * - * @see Viva.Graph.View.webglLinkShader.position - */ -Viva.Graph.View.webglLine = function (color) { - return { - /** - * Gets or sets color of the line. If you set this property externally - * make sure it always come as integer of 0xRRGGBBAA format - */ - color : Viva.Graph.View._webglUtil.parseColor(color) - }; -}; - -/** - * Can be used as a callback in the webglGraphics.node() function, to - * create a custom looking node. - * - * @param size - size of the node in pixels. - * @param color - color of the node in '#rrggbbaa' or '#rgb' format. - */ -Viva.Graph.View.webglSquare = function (size, color) { - return { - /** - * Gets or sets size of the square side. - */ - size : typeof size === 'number' ? size : 10, - - /** - * Gets or sets color of the square. - */ - color : Viva.Graph.View._webglUtil.parseColor(color) - }; -}; - -/** - * Represents a model for image. - */ -Viva.Graph.View.webglImage = function (size, src) { - return { - /** - * Gets texture index where current image is placed. - */ - _texture : 0, - - /** - * Gets offset in the texture where current image is placed. - */ - _offset : 0, - - /** - * Gets size of the square with the image. - */ - size : typeof size === 'number' ? size : 32, - - /** - * Source of the image. If image is coming not from your domain - * certain origin restrictions applies. - * See http://www.khronos.org/registry/webgl/specs/latest/#4.2 for more details. - */ - src : src - }; -}; diff --git a/src/version.js b/src/version.js index c756618..7fb0fc0 100644 --- a/src/version.js +++ b/src/version.js @@ -1 +1,2 @@ -Viva.Graph.version = '0.6.0'; + +module.exports = '0.7.0.alpha'; diff --git a/src/viva.js b/src/viva.js new file mode 100644 index 0000000..4f7b0ac --- /dev/null +++ b/src/viva.js @@ -0,0 +1,32 @@ +/** + * This is an entry point for global namespace. If you want to use separate + * modules individually - you are more than welcome to do so. + */ +var Viva = {}; + +Viva.Graph = { + version: require('./version.js'), + graph: require('ngraph.graph'), + + webgl: require('./WebGL/webgl.js'), + webglInputEvents: require('./WebGL/webglInputEvents.js'), + + View: { + // TODO: Move these out to webgl namespace + Texture: require('./WebGL/texture.js'), + // TODO: This should not be even exported + webglAtlas: require('./WebGL/webglAtlas.js'), + webglImageNodeProgram: require('./WebGL/webglImageNodeProgram.js'), + webglLinkProgram: require('./WebGL/webglLinkProgram.js'), + webglNodeProgram: require('./WebGL/webglNodeProgram.js'), + webglLine: require('./WebGL/webglLine.js'), + webglSquare: require('./WebGL/webglSquare.js'), + webglImage: require('./WebGL/webglImage.js'), + // TODO: Deprecate this: + _webglUtil: { + parseColor: require('./WebGL/parseColor.js') + } + } +}; + +module.exports = Viva; diff --git a/src/vivagraph.js b/src/vivagraph.js deleted file mode 100644 index e1faaac..0000000 --- a/src/vivagraph.js +++ /dev/null @@ -1,9 +0,0 @@ -/** - * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka - */ -var Viva = Viva || {}; - -Viva.Graph = Viva.Graph || {}; -if (typeof module !== 'undefined' && module.exports) { - module.exports = Viva; -} From 952d519e0950268ecafaa7575c3e7623d2a87053 Mon Sep 17 00:00:00 2001 From: anvaka Date: Fri, 9 Jan 2015 00:32:51 -0800 Subject: [PATCH 118/276] Removed old comment --- src/WebGL/webglLine.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/WebGL/webglLine.js b/src/WebGL/webglLine.js index 9fbe352..cef60be 100644 --- a/src/WebGL/webglLine.js +++ b/src/WebGL/webglLine.js @@ -7,7 +7,6 @@ module.exports = webglLine; * it's just passed to corresponding shader and the shader should * figure out how to render it. * - * @see Viva.Graph.View.webglLinkShader.position */ function webglLine(color) { return { From 1de05507fa2101fbb20d4c28a1f1d19e76541e39 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 10 Jan 2015 11:50:32 -0800 Subject: [PATCH 119/276] Removed cssGraphcis --- demos/other/d3sampleTest.html | 22 --- src/View/cssGraphics.js | 324 ---------------------------------- src/View/renderer.js | 1 - src/viva.js | 7 +- 4 files changed, 6 insertions(+), 348 deletions(-) delete mode 100644 src/View/cssGraphics.js diff --git a/demos/other/d3sampleTest.html b/demos/other/d3sampleTest.html index 266e95c..dc94d53 100644 --- a/demos/other/d3sampleTest.html +++ b/demos/other/d3sampleTest.html @@ -49,17 +49,6 @@ gravity : -1 }); - var cssGraphics = Viva.Graph.View.cssGraphics(); - - cssGraphics.node(function(node){ - var nodeUI = document.createElement('div'); - nodeUI.setAttribute('class', 'node'); - nodeUI.title = node.data.name; - var groupId = node.data.group; - nodeUI.style.background = colors[groupId ? groupId - 1 : 5]; - return nodeUI; - }); - var svgGraphics = Viva.Graph.View.svgGraphics(); svgGraphics.node(function(node){ var groupId = node.data.group; @@ -96,17 +85,6 @@ } - - -
-
-
- - From fcd6e44c53ba2777f9153754f6e788d6b57dc10d Mon Sep 17 00:00:00 2001 From: anvaka Date: Tue, 3 Feb 2015 23:48:15 -0800 Subject: [PATCH 154/276] Use symmetric API for constantLayout --- src/Layout/constant.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Layout/constant.js b/src/Layout/constant.js index 21efe78..758c51a 100644 --- a/src/Layout/constant.js +++ b/src/Layout/constant.js @@ -154,8 +154,8 @@ function constant(graph, userSettings) { /** * Sets position of a node to a given coordinates */ - setNodePosition: function (node, x, y) { - var pos = layoutNodes[node.id]; + setNodePosition: function (nodeId, x, y) { + var pos = layoutNodes[nodeId]; if (pos) { pos.x = x; pos.y = y; From f69abb370818ec914a3fc82b2a940129efa84ff7 Mon Sep 17 00:00:00 2001 From: anvaka Date: Tue, 3 Feb 2015 23:48:41 -0800 Subject: [PATCH 155/276] Spelling --- CHANGELOG | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 35abb5e..09f7dc3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,20 +4,28 @@ v0.7.0 - `Viva.Graph.svg` is replaced with npm module `simplesvg` - `Viva.Graph.graph` is replaced with `ngraph.graph` - `Viva.Graph.generator` is replaced with `ngraph.generators`. This module - contains all original grpah + new graphs. + contains all original graph + new graphs. Note: `randomNoLinks` is called `noLinks`. - `Viva.graph.Layout.forceDirected` is replaced with npm module 'ngraph.forcelayout'. This module is faster than older one, and has better - test coverage. One major difference, is that now instead of passing `link` - object to `layout.getLinkPosition(link)`, you need to pas linkId: - `layout.getLinkPosition(link.id)` + test coverage. Unfortunately this also means breaking changes: + 1. Instead of passing `link` object to `layout.getLinkPosition(link)`, you + need to pas linkId: `layout.getLinkPosition(link.id)`. + 2. Instead of passing `node` object to `layout.setNodePosition(node, x, y)` + use `layout.setNodePosition(node.id, x, y)`. + 3. Force based layout settings can be now accessed from `layout.simulator`: + `layout.drag()` is now known as `simulator.dragCoeff()` + `layout.springCoeff()` -> `simulator.springCoeff()` + `layout.springLength()` -> `simulator.springLength()` + `layout.gravity()` -> `simulator.gravity()` + `layout.theta()` -> `simulator.theta()` - `Viva.Graph.Point2d` is removed. Use plain {x: 42, y: 42} object - `Viva.Graph.graph.addEventListener` is replaced with `on` method - `Viva.Graph.View.cssGraphcis` is deprecated - `Viva.Graph.View.svgNodeFactory` is deprecated - `geom.convexHull` is deprecated. Use https://github.com/anvaka/cnvx instead. - - `Viva.Grpah.community` is deprecated. Use https://github.com/anvaka/ngraph.slpa + - `Viva.Graph.community` is deprecated. Use https://github.com/anvaka/ngraph.slpa instead. v0.6.0 From d34bc8abb95de6f6a84e17be675cf06f62af1e53 Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 4 Feb 2015 00:13:40 -0800 Subject: [PATCH 156/276] Updated readme --- README.md | 85 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 52 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index b5b903d..cfe5a99 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,9 @@ -Graph Drawing Library +VivaGraph [![Build Status](https://travis-ci.org/anvaka/VivaGraphJS.svg)](https://travis-ci.org/anvaka/VivaGraphJS) ================================================== -**VivaGraphJS** is a free [graph drawing](http://en.wikipedia.org/wiki/Graph_drawing) library for JavaScript. -It is designed to be extensible and to support different rendering engines and layout algorithms. At the moment -it supports rendering graphs using WebGL, SVG or CSS formats. - -**Note:** Please visit [anvaka/ngraph](https://github.com/anvaka/ngraph) to check -next evolution step of this library. `ngraph` supports rendering graphs to images, -3D graphs rendering, integration with [gephi](https://gephi.org/) and more. - +**VivaGraphJS** is a free [graph drawing](http://en.wikipedia.org/wiki/Graph_drawing) +library for JavaScript. It is designed to be extensible and to support different +rendering engines and layout algorithms. At the moment it supports rendering +graphs using WebGL and SVG. Enough talking. Show me the demo! ---------------------------------------------------- @@ -19,7 +15,8 @@ Some examples of library usage in the real projects: * [Graph Viewer](http://www.yasiv.com/graphs#Bai/rw496) visualization of sparse matrices collection of the University of Florida. WebGL based. * [Vkontakte Visualization](http://www.yasiv.com/vk) friendship visualization of the largest social network in Russia [vk.com](vk.com). WebGL based. -To start using the library include `vivagraph.js` script from the [dist](https://github.com/anvaka/VivaGraphJS/tree/master/dist) folder. The following code is the minimum required to render a graph with two nodes and one edge: +To start using the library include `vivagraph.js` script from the [dist](https://github.com/anvaka/VivaGraphJS/tree/master/dist) +folder. The following code is the minimum required to render a graph with two nodes and one edge: ```javascript var graph = Viva.Graph.graph(); @@ -33,8 +30,8 @@ This will produce the following layout: ![Simple graph](https://github.com/anvaka/VivaGraphJS/raw/master/packages/Images/mingraph.png) -The code above adds a link to the graph between nodes `1` and `2`. Since nodes are not yet in the graph -they will be created. It's equivalent to +The code above adds a link to the graph between nodes `1` and `2`. Since nodes +are not yet in the graph they will be created. It's equivalent to ```javascript var graph = Viva.Graph.graph(); @@ -46,18 +43,20 @@ var renderer = Viva.Graph.View.renderer(graph); renderer.run(); ``` - Customization ---------------------------------------------------- -VivaGraphJS is all about customization. You can easily change the appearance of nodes and links. You can also change the layouting algorithm and medium that displays elements of the graph. For example: The following code allows you to use CSS-based rendering, instead of the default SVG. +VivaGraphJS is all about customization. You can easily change the appearance of +nodes and links. You can also change the layouting algorithm and medium that +displays elements of the graph. For example: The following code allows you to +use WebGL-based rendering, instead of the default SVG. ```javascript var graph = Viva.Graph.graph(); graph.addLink(1, 2); -var graphics = Viva.Graph.View.cssGraphics(); +var graphics = Viva.Graph.View.webglGraphics(); -var renderer = Viva.Graph.View.renderer(graph, +var renderer = Viva.Graph.View.renderer(graph, { graphics : graphics }); @@ -99,7 +98,7 @@ graphics.node(function(node) { nodeUI.attr('x', pos.x - 12).attr('y', pos.y - 12); }); -var renderer = Viva.Graph.View.renderer(graph, +var renderer = Viva.Graph.View.renderer(graph, { graphics : graphics }); @@ -123,7 +122,9 @@ var renderer = Viva.Graph.View.renderer(graph); renderer.run(); ``` -Graph generators are part of the library, which can produce classic graphs. `grid` generator creates a grid with given number of columns and rows. But with default parameters the rendering is pretty ugly: +Graph generators are part of the library, which can produce classic graphs. +`grid` generator creates a grid with given number of columns and rows. But with +default parameters the rendering is pretty ugly: ![Grid 3x3 bad](https://github.com/anvaka/VivaGraphJS/raw/master/packages/Images/gridBad.png) @@ -150,8 +151,27 @@ Now the result is much better: ![Grid 3x3](https://github.com/anvaka/VivaGraphJS/raw/master/packages/Images/gridGood.png) -Tuning layout algorithm is definitely one of the hardest part of using this library. It has to be improved in future to simplify usage. Each of the force directed algorithm parameters are described in the source code. +Tuning layout algorithm is definitely one of the hardest part of using this library. +It has to be improved in future to simplify usage. Each of the force directed +algorithm parameters are described in the source code. + +Design philosophy/roadmap +------------------------- + +Until version 0.7.x VivaGraph was a single monolithic code base. Starting from +0.7.x the library is bundled from small npm modules into `Viva` namespace. +All these modules are part of a larger [ngraph](https://github.com/anvaka/ngraph) +family. `ngraph` modules support rendering graphs into images, 3D rendering, +integration with [gephi](https://gephi.org/), pagerank calculation and many more. +Version 0.7 is a compromise between maximum backward compatibility and ngraph +flexibility. Eventually I hope to further simplify API and provide interface +for custom builds. + +Upgrade guide +------------- + +Please refer the [upgrade guide](https://github.com/anvaka/VivaGraphJS/blob/master/docs/upgrade_guide.md) to see how to update older versions of the library to the latest one. Local Build ----------- @@ -160,15 +180,10 @@ Run the following script: git clone git://github.com/anvaka/VivaGraphJS.git cd ./VivaGraphJS npm install -grunt +gulp release ``` The combined/minified code should be stored in ```dist``` folder. -Upgrade guide -------------- - -Please refer the [upgrade guide](https://github.com/anvaka/VivaGraphJS/blob/master/docs/upgrade_guide.md) to see how to update older versions of the library to the latest one. - Looking for alternatives? ------------------------- @@ -177,11 +192,15 @@ Please [find it here](http://anvaka.github.io/graph-drawing-libraries/#/all) I need your feedback ---------------------------------------------------- -Disclaimer: I wrote this library to learn JavaScript. By no means I pretend to be an expert in the language and chosen approach to design may not be the optimal. I would love to hear your feedback and suggestions. - -Though I implemented this library from scratch, I went through many existing libraries to pick the best (at my view) out of them. If you are evaluating libraries for your project make sure to check them out as well: - -* [Dracula Graph Library](https://github.com/strathausen/dracula) - written by [Johann Philipp Strathausen](https://github.com/strathausen) and uses [Raphaël](http://raphaeljs.com/) library to render graphs. Has very simple API. -* [D3](http://mbostock.github.com/d3/ex/force.html) - one of the best data visualization library in JavaScript world. From [Mike Bostock](https://github.com/mbostock). - -My goal is to create highly performant javascript library, which serves in the field of graph drawing. To certain extent I achieved it. But I have no doubt there is much more to improve here. +Disclaimer: I wrote this library to learn JavaScript. By no means I pretend to +be an expert in the language and chosen approach to design may not be the optimal. +I would love to hear your feedback and suggestions. + +Though I implemented this library from scratch, I went through many existing +libraries to pick the best (at my view) out of them. If you are evaluating libraries +for your project make sure to [check them out](http://anvaka.github.io/graph-drawing-libraries/#/all) +as well. + +My goal is to create highly performant javascript library, which serves in the +field of graph drawing. To certain extent I achieved it. But I have no doubt +there is much more to improve here. From 558f2a14df682bb26840516d0cf29eb370276432 Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 4 Feb 2015 00:16:13 -0800 Subject: [PATCH 157/276] Releasing 0.7 --- CHANGELOG | 2 +- dist/vivagraph.js | 420 +++++++++++++++++++++++------------------- dist/vivagraph.min.js | 4 +- src/version.js | 3 +- 4 files changed, 237 insertions(+), 192 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 09f7dc3..989bc73 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,5 @@ v0.7.0 - date TBD + date Feb 4, 2014 - All files are now CommonJS Modules - `Viva.Graph.svg` is replaced with npm module `simplesvg` - `Viva.Graph.graph` is replaced with `ngraph.graph` diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 6ce186f..c16e771 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -58,10 +58,7 @@ Viva.Graph = { findElementPosition: require('./Utils/findElementPosition.js'), timer: require('./Utils/timer.js'), getDimension: require('./Utils/getDimensions.js'), - events: function(g) { - console.log("This method is deprecated. Please use graph.on()/grpah.off() directly"); - return g; - } + events: require('./Utils/backwardCompatibleEvents.js') }, Layout: { @@ -119,7 +116,7 @@ Viva.Graph = { module.exports = Viva; -},{"./Algorithms/centrality.js":35,"./Algorithms/operations.js":36,"./Input/domInputManager.js":37,"./Input/dragndrop.js":38,"./Input/webglInputManager.js":39,"./Layout/constant.js":40,"./Utils/browserInfo.js":41,"./Utils/findElementPosition.js":43,"./Utils/getDimensions.js":44,"./Utils/intersectRect.js":45,"./Utils/rect.js":47,"./Utils/timer.js":48,"./View/renderer.js":50,"./View/svgGraphics.js":51,"./View/webglGraphics.js":52,"./WebGL/parseColor.js":53,"./WebGL/texture.js":54,"./WebGL/webgl.js":55,"./WebGL/webglAtlas.js":56,"./WebGL/webglImage.js":57,"./WebGL/webglImageNodeProgram.js":58,"./WebGL/webglInputEvents.js":59,"./WebGL/webglLine.js":60,"./WebGL/webglLinkProgram.js":61,"./WebGL/webglNodeProgram.js":62,"./WebGL/webglSquare.js":63,"./version.js":64,"gintersect":2,"ngraph.events":6,"ngraph.forcelayout":7,"ngraph.fromjson":24,"ngraph.generators":25,"ngraph.graph":26,"ngraph.merge":27,"ngraph.random":28,"ngraph.tojson":29,"simplesvg":30}],2:[function(require,module,exports){ +},{"./Algorithms/centrality.js":33,"./Algorithms/operations.js":34,"./Input/domInputManager.js":35,"./Input/dragndrop.js":36,"./Input/webglInputManager.js":37,"./Layout/constant.js":38,"./Utils/backwardCompatibleEvents.js":39,"./Utils/browserInfo.js":40,"./Utils/findElementPosition.js":42,"./Utils/getDimensions.js":43,"./Utils/intersectRect.js":44,"./Utils/rect.js":46,"./Utils/timer.js":47,"./View/renderer.js":49,"./View/svgGraphics.js":50,"./View/webglGraphics.js":51,"./WebGL/parseColor.js":52,"./WebGL/texture.js":53,"./WebGL/webgl.js":54,"./WebGL/webglAtlas.js":55,"./WebGL/webglImage.js":56,"./WebGL/webglImageNodeProgram.js":57,"./WebGL/webglInputEvents.js":58,"./WebGL/webglLine.js":59,"./WebGL/webglLinkProgram.js":60,"./WebGL/webglNodeProgram.js":61,"./WebGL/webglSquare.js":62,"./version.js":63,"gintersect":2,"ngraph.events":6,"ngraph.forcelayout":7,"ngraph.fromjson":22,"ngraph.generators":23,"ngraph.graph":24,"ngraph.merge":25,"ngraph.random":26,"ngraph.tojson":27,"simplesvg":28}],2:[function(require,module,exports){ module.exports = intersect; /** @@ -796,7 +793,7 @@ function createLayout(graph, physicsSimulator) { function noop() { } -},{"ngraph.physics.simulator":8,"varta":23}],8:[function(require,module,exports){ +},{"ngraph.physics.simulator":8,"varta":21}],8:[function(require,module,exports){ /** * Manages a simulation of physical forces acting on bodies and springs. */ @@ -1052,7 +1049,7 @@ function physicsSimulator(settings) { } }; -},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":16,"ngraph.quadtreebh":18}],9:[function(require,module,exports){ +},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":25,"ngraph.quadtreebh":17}],9:[function(require,module,exports){ module.exports = function (bodies, settings) { var random = require('ngraph.random').random(42); var boundingBox = { x1: 0, y1: 0, x2: 0, y2: 0 }; @@ -1134,14 +1131,14 @@ module.exports = function (bodies, settings) { } } -},{"ngraph.random":22}],10:[function(require,module,exports){ +},{"ngraph.random":26}],10:[function(require,module,exports){ var physics = require('ngraph.physics.primitives'); module.exports = function(pos) { return new physics.Body(pos); } -},{"ngraph.physics.primitives":17}],11:[function(require,module,exports){ +},{"ngraph.physics.primitives":16}],11:[function(require,module,exports){ /** * Represents drag force, which reduces force value on each step by given * coefficient. @@ -1170,7 +1167,7 @@ module.exports = function (options) { return api; }; -},{"ngraph.expose":15,"ngraph.merge":16}],12:[function(require,module,exports){ +},{"ngraph.expose":15,"ngraph.merge":25}],12:[function(require,module,exports){ /** * Performs forces integration, using given timestep. Uses Euler method to solve * differential equation (http://en.wikipedia.org/wiki/Euler_method ). @@ -1281,7 +1278,7 @@ module.exports = function (options) { return api; } -},{"ngraph.expose":15,"ngraph.merge":16,"ngraph.random":22}],15:[function(require,module,exports){ +},{"ngraph.expose":15,"ngraph.merge":25,"ngraph.random":26}],15:[function(require,module,exports){ module.exports = exposeProperties; /** @@ -1328,39 +1325,6 @@ function augment(source, target, key) { } },{}],16:[function(require,module,exports){ -module.exports = merge; - -/** - * Augments `target` with properties in `options`. Does not override - * target's properties if they are defined and matches expected type in - * options - * - * @returns {Object} merged object - */ -function merge(target, options) { - var key; - if (!target) { target = {}; } - if (options) { - for (key in options) { - if (options.hasOwnProperty(key)) { - var targetHasIt = target.hasOwnProperty(key), - optionsValueType = typeof options[key], - shouldReplace = !targetHasIt || (typeof target[key] !== optionsValueType); - - if (shouldReplace) { - target[key] = options[key]; - } else if (optionsValueType === 'object') { - // go deep, don't care about loops here, we are simple API!: - target[key] = merge(target[key], options[key]); - } - } - } - } - - return target; -} - -},{}],17:[function(require,module,exports){ module.exports = { Body: Body, Vector2d: Vector2d, @@ -1427,7 +1391,7 @@ Vector3d.prototype.reset = function () { this.x = this.y = this.z = 0; }; -},{}],18:[function(require,module,exports){ +},{}],17:[function(require,module,exports){ /** * This is Barnes Hut simulation algorithm for 2d case. Implementation * is highly optimized (avoids recusion and gc pressure) @@ -1740,7 +1704,7 @@ module.exports = function(options) { }; }; -},{"./insertStack":19,"./isSamePosition":20,"./node":21,"ngraph.random":22}],19:[function(require,module,exports){ +},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":26}],18:[function(require,module,exports){ module.exports = InsertStack; /** @@ -1784,7 +1748,7 @@ function InsertStackElement(node, body) { this.body = body; // physical body which needs to be inserted to node } -},{}],20:[function(require,module,exports){ +},{}],19:[function(require,module,exports){ module.exports = function isSamePosition(point1, point2) { var dx = Math.abs(point1.x - point2.x); var dy = Math.abs(point1.y - point2.y); @@ -1792,7 +1756,7 @@ module.exports = function isSamePosition(point1, point2) { return (dx < 1e-8 && dy < 1e-8); }; -},{}],21:[function(require,module,exports){ +},{}],20:[function(require,module,exports){ /** * Internal data structure to represent 2D QuadTree node */ @@ -1821,94 +1785,7 @@ module.exports = function Node() { this.right = 0; }; -},{}],22:[function(require,module,exports){ -module.exports = { - random: random, - randomIterator: randomIterator -}; - -/** - * Creates seeded PRNG with two methods: - * next() and nextDouble() - */ -function random(inputSeed) { - var seed = typeof inputSeed === 'number' ? inputSeed : (+ new Date()); - var randomFunc = function() { - // Robert Jenkins' 32 bit integer hash function. - seed = ((seed + 0x7ed55d16) + (seed << 12)) & 0xffffffff; - seed = ((seed ^ 0xc761c23c) ^ (seed >>> 19)) & 0xffffffff; - seed = ((seed + 0x165667b1) + (seed << 5)) & 0xffffffff; - seed = ((seed + 0xd3a2646c) ^ (seed << 9)) & 0xffffffff; - seed = ((seed + 0xfd7046c5) + (seed << 3)) & 0xffffffff; - seed = ((seed ^ 0xb55a4f09) ^ (seed >>> 16)) & 0xffffffff; - return (seed & 0xfffffff) / 0x10000000; - }; - - return { - /** - * Generates random integer number in the range from 0 (inclusive) to maxValue (exclusive) - * - * @param maxValue Number REQUIRED. Ommitting this number will result in NaN values from PRNG. - */ - next : function (maxValue) { - return Math.floor(randomFunc() * maxValue); - }, - - /** - * Generates random double number in the range from 0 (inclusive) to 1 (exclusive) - * This function is the same as Math.random() (except that it could be seeded) - */ - nextDouble : function () { - return randomFunc(); - } - }; -} - -/* - * Creates iterator over array, which returns items of array in random order - * Time complexity is guaranteed to be O(n); - */ -function randomIterator(array, customRandom) { - var localRandom = customRandom || random(); - if (typeof localRandom.next !== 'function') { - throw new Error('customRandom does not match expected API: next() function is missing'); - } - - return { - forEach : function (callback) { - var i, j, t; - for (i = array.length - 1; i > 0; --i) { - j = localRandom.next(i + 1); // i inclusive - t = array[j]; - array[j] = array[i]; - array[i] = t; - - callback(t); - } - - if (array.length) { - callback(array[0]); - } - }, - - /** - * Shuffles array randomly, in place. - */ - shuffle : function () { - var i, j, t; - for (i = array.length - 1; i > 0; --i) { - j = localRandom.next(i + 1); // i inclusive - t = array[j]; - array[j] = array[i]; - array[i] = t; - } - - return array; - } - }; -} - -},{}],23:[function(require,module,exports){ +},{}],21:[function(require,module,exports){ module.exports = varta; module.exports.has = delayedVerify; @@ -1948,7 +1825,7 @@ function internalVerify(suspect, name, expectations) { return true; } -},{}],24:[function(require,module,exports){ +},{}],22:[function(require,module,exports){ module.exports = load; var createGraph = require('ngraph.graph'); @@ -1993,7 +1870,7 @@ function load(jsonGraph, nodeTransform, linkTransform) { function id(x) { return x; } -},{"ngraph.graph":26}],25:[function(require,module,exports){ +},{"ngraph.graph":24}],23:[function(require,module,exports){ module.exports = { ladder: ladder, complete: complete, @@ -2294,7 +2171,7 @@ function wattsStrogatz(n, k, p, seed) { return g; } -},{"ngraph.graph":26,"ngraph.random":28}],26:[function(require,module,exports){ +},{"ngraph.graph":24,"ngraph.random":26}],24:[function(require,module,exports){ /** * @fileOverview Contains definition of the core graph object. */ @@ -2600,7 +2477,10 @@ function createGraph() { // TODO: this is not cool. On large graphs potentially would consume more memory. fromNode.links.push(link); - toNode.links.push(link); + if (fromId !== toId) { + // make sure we are not duplicating links for self-loops + toNode.links.push(link); + } recordLinkChange(link, 'add'); @@ -2801,11 +2681,127 @@ function Link(fromId, toId, data, id) { this.id = id; } -},{"ngraph.events":6}],27:[function(require,module,exports){ -arguments[4][16][0].apply(exports,arguments) -},{"dup":16}],28:[function(require,module,exports){ -arguments[4][22][0].apply(exports,arguments) -},{"dup":22}],29:[function(require,module,exports){ +},{"ngraph.events":6}],25:[function(require,module,exports){ +module.exports = merge; + +/** + * Augments `target` with properties in `options`. Does not override + * target's properties if they are defined and matches expected type in + * options + * + * @returns {Object} merged object + */ +function merge(target, options) { + var key; + if (!target) { target = {}; } + if (options) { + for (key in options) { + if (options.hasOwnProperty(key)) { + var targetHasIt = target.hasOwnProperty(key), + optionsValueType = typeof options[key], + shouldReplace = !targetHasIt || (typeof target[key] !== optionsValueType); + + if (shouldReplace) { + target[key] = options[key]; + } else if (optionsValueType === 'object') { + // go deep, don't care about loops here, we are simple API!: + target[key] = merge(target[key], options[key]); + } + } + } + } + + return target; +} + +},{}],26:[function(require,module,exports){ +module.exports = { + random: random, + randomIterator: randomIterator +}; + +/** + * Creates seeded PRNG with two methods: + * next() and nextDouble() + */ +function random(inputSeed) { + var seed = typeof inputSeed === 'number' ? inputSeed : (+ new Date()); + var randomFunc = function() { + // Robert Jenkins' 32 bit integer hash function. + seed = ((seed + 0x7ed55d16) + (seed << 12)) & 0xffffffff; + seed = ((seed ^ 0xc761c23c) ^ (seed >>> 19)) & 0xffffffff; + seed = ((seed + 0x165667b1) + (seed << 5)) & 0xffffffff; + seed = ((seed + 0xd3a2646c) ^ (seed << 9)) & 0xffffffff; + seed = ((seed + 0xfd7046c5) + (seed << 3)) & 0xffffffff; + seed = ((seed ^ 0xb55a4f09) ^ (seed >>> 16)) & 0xffffffff; + return (seed & 0xfffffff) / 0x10000000; + }; + + return { + /** + * Generates random integer number in the range from 0 (inclusive) to maxValue (exclusive) + * + * @param maxValue Number REQUIRED. Ommitting this number will result in NaN values from PRNG. + */ + next : function (maxValue) { + return Math.floor(randomFunc() * maxValue); + }, + + /** + * Generates random double number in the range from 0 (inclusive) to 1 (exclusive) + * This function is the same as Math.random() (except that it could be seeded) + */ + nextDouble : function () { + return randomFunc(); + } + }; +} + +/* + * Creates iterator over array, which returns items of array in random order + * Time complexity is guaranteed to be O(n); + */ +function randomIterator(array, customRandom) { + var localRandom = customRandom || random(); + if (typeof localRandom.next !== 'function') { + throw new Error('customRandom does not match expected API: next() function is missing'); + } + + return { + forEach : function (callback) { + var i, j, t; + for (i = array.length - 1; i > 0; --i) { + j = localRandom.next(i + 1); // i inclusive + t = array[j]; + array[j] = array[i]; + array[i] = t; + + callback(t); + } + + if (array.length) { + callback(array[0]); + } + }, + + /** + * Shuffles array randomly, in place. + */ + shuffle : function () { + var i, j, t; + for (i = array.length - 1; i > 0; --i) { + j = localRandom.next(i + 1); // i inclusive + t = array[j]; + array[j] = array[i]; + array[i] = t; + } + + return array; + } + }; +} + +},{}],27:[function(require,module,exports){ module.exports = save; function save(graph, customNodeTransform, customLinkTransform) { @@ -2861,7 +2857,7 @@ function save(graph, customNodeTransform, customLinkTransform) { } } -},{}],30:[function(require,module,exports){ +},{}],28:[function(require,module,exports){ module.exports = svg; svg.compile = require('./lib/compile'); @@ -2974,7 +2970,7 @@ function augment(element) { } } -},{"./lib/compile":31,"./lib/compileTemplate":32,"add-event-listener":34}],31:[function(require,module,exports){ +},{"./lib/compile":29,"./lib/compileTemplate":30,"add-event-listener":32}],29:[function(require,module,exports){ var parser = require('./domparser.js'); var svg = require('../'); @@ -3002,7 +2998,7 @@ function addNamespaces(text) { } } -},{"../":30,"./domparser.js":33}],32:[function(require,module,exports){ +},{"../":28,"./domparser.js":31}],30:[function(require,module,exports){ module.exports = template; var BINDING_EXPR = /{{(.+?)}}/; @@ -3096,7 +3092,7 @@ function bindTextContent(element, allBindings) { } } -},{}],33:[function(require,module,exports){ +},{}],31:[function(require,module,exports){ module.exports = createDomparser(); function createDomparser() { @@ -3112,7 +3108,7 @@ function fail() { throw new Error('DOMParser is not supported by this platform. Please open issue here https://github.com/anvaka/simplesvg'); } -},{}],34:[function(require,module,exports){ +},{}],32:[function(require,module,exports){ addEventListener.removeEventListener = removeEventListener addEventListener.addEventListener = addEventListener @@ -3160,7 +3156,7 @@ function oldIEDetach(el, eventName, listener, useCapture) { el.detachEvent('on' + eventName, listener) } -},{}],35:[function(require,module,exports){ +},{}],33:[function(require,module,exports){ var centrality = require('ngraph.centrality'); module.exports = centralityWrapper; @@ -3198,7 +3194,7 @@ function toVivaGraphCentralityFormat(centrality) { } } -},{"ngraph.centrality":3}],36:[function(require,module,exports){ +},{"ngraph.centrality":3}],34:[function(require,module,exports){ /** * @fileOverview Contains collection of primitive operations under graph. * @@ -3233,7 +3229,7 @@ function operations() { }; }; -},{}],37:[function(require,module,exports){ +},{}],35:[function(require,module,exports){ /** * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ @@ -3280,7 +3276,7 @@ function domInputManager(graph, graphics) { }; } -},{"./dragndrop.js":38}],38:[function(require,module,exports){ +},{"./dragndrop.js":36}],36:[function(require,module,exports){ /** * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ @@ -3563,7 +3559,7 @@ function dragndrop(element) { }; } -},{"../Utils/browserInfo.js":41,"../Utils/documentEvents.js":42,"../Utils/findElementPosition.js":43}],39:[function(require,module,exports){ +},{"../Utils/browserInfo.js":40,"../Utils/documentEvents.js":41,"../Utils/findElementPosition.js":42}],37:[function(require,module,exports){ /** * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ @@ -3634,7 +3630,7 @@ function webglInputManager(graph, graphics) { }; } -},{"../WebGL/webglInputEvents.js":59}],40:[function(require,module,exports){ +},{"../WebGL/webglInputEvents.js":58}],38:[function(require,module,exports){ module.exports = constant; var merge = require('ngraph.merge'); @@ -3791,8 +3787,8 @@ function constant(graph, userSettings) { /** * Sets position of a node to a given coordinates */ - setNodePosition: function (node, x, y) { - var pos = layoutNodes[node.id]; + setNodePosition: function (nodeId, x, y) { + var pos = layoutNodes[nodeId]; if (pos) { pos.x = x; pos.y = y; @@ -3833,7 +3829,52 @@ function constant(graph, userSettings) { } } -},{"../Utils/rect.js":47,"ngraph.merge":27,"ngraph.random":28}],41:[function(require,module,exports){ +},{"../Utils/rect.js":46,"ngraph.merge":25,"ngraph.random":26}],39:[function(require,module,exports){ +/** + * This module provides compatibility layer with 0.6.x library. It will be + * removed in the next version + */ + +var events = require('ngraph.events'); + +module.exports = backwardCompatibleEvents; + +function backwardCompatibleEvents(g) { + console.log("This method is deprecated. Please use Viva.events() instead"); + + if (!g) { + return g; + } + + var eventsDefined = (g.on !== undefined) || + (g.off !== undefined) || + (g.fire !== undefined); + + if (eventsDefined) { + // events already defined, ignore + return { + extend: function() { + return g; + }, + on: g.on, + stop: g.off + }; + } + + return { + extend: extend, + on: g.on, + stop: g.off + }; + + function extend() { + var backwardCompatible = events(g); + backwardCompatible.addEventListener = backwardCompatible.on; + return backwardCompatible; + } +} + +},{"ngraph.events":6}],40:[function(require,module,exports){ module.exports = browserInfo(); function browserInfo() { @@ -3862,7 +3903,7 @@ function browserInfo() { }; } -},{}],42:[function(require,module,exports){ +},{}],41:[function(require,module,exports){ var nullEvents = require('./nullEvents.js'); module.exports = createDocumentEvents(); @@ -3886,7 +3927,7 @@ function off(eventName, handler) { document.removeEventListener(eventName, handler); } -},{"./nullEvents.js":46}],43:[function(require,module,exports){ +},{"./nullEvents.js":45}],42:[function(require,module,exports){ /** * Finds the absolute position of an element on a page */ @@ -3905,7 +3946,7 @@ function findElementPosition(obj) { return [curleft, curtop]; } -},{}],44:[function(require,module,exports){ +},{}],43:[function(require,module,exports){ module.exports = getDimension; function getDimension(container) { @@ -3927,7 +3968,7 @@ function getDimension(container) { }; } -},{}],45:[function(require,module,exports){ +},{}],44:[function(require,module,exports){ var intersect = require('gintersect'); module.exports = intersectRect; @@ -3939,7 +3980,7 @@ function intersectRect(left, top, right, bottom, x1, y1, x2, y2) { intersect(right, top, left, top, x1, y1, x2, y2); } -},{"gintersect":2}],46:[function(require,module,exports){ +},{"gintersect":2}],45:[function(require,module,exports){ module.exports = createNullEvents(); function createNullEvents() { @@ -3952,7 +3993,7 @@ function createNullEvents() { function noop() { } -},{}],47:[function(require,module,exports){ +},{}],46:[function(require,module,exports){ module.exports = Rect; /** @@ -3965,7 +4006,7 @@ function Rect (x1, y1, x2, y2) { this.y2 = y2 || 0; } -},{}],48:[function(require,module,exports){ +},{}],47:[function(require,module,exports){ (function (global){ /** * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com @@ -4050,7 +4091,7 @@ function createTimer() { } }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],49:[function(require,module,exports){ +},{}],48:[function(require,module,exports){ var nullEvents = require('./nullEvents.js'); module.exports = createDocumentEvents(); @@ -4075,7 +4116,7 @@ function off(eventName, handler) { } -},{"./nullEvents.js":46}],50:[function(require,module,exports){ +},{"./nullEvents.js":45}],49:[function(require,module,exports){ /** * @fileOverview Defines a graph renderer that uses CSS based drawings. * @@ -4540,7 +4581,7 @@ function renderer(graph, settings) { }; } -},{"../Input/domInputManager.js":37,"../Input/dragndrop.js":38,"../Utils/getDimensions.js":44,"../Utils/timer.js":48,"../Utils/windowEvents.js":49,"./svgGraphics.js":51,"ngraph.forcelayout":7,"ngraph.graph":26}],51:[function(require,module,exports){ +},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.forcelayout":7,"ngraph.graph":24}],50:[function(require,module,exports){ /** * @fileOverview Defines a graph renderer that uses SVG based drawings. * @@ -4898,7 +4939,7 @@ function svgGraphics() { } } -},{"../Input/domInputManager.js":37,"ngraph.events":6,"simplesvg":30}],52:[function(require,module,exports){ +},{"../Input/domInputManager.js":35,"ngraph.events":6,"simplesvg":28}],51:[function(require,module,exports){ /** * @fileOverview Defines a graph renderer that uses WebGL based drawings. * @@ -5446,7 +5487,7 @@ function webglGraphics(options) { return graphics; } -},{"../Input/webglInputManager.js":39,"../WebGL/webglLine.js":60,"../WebGL/webglLinkProgram.js":61,"../WebGL/webglNodeProgram.js":62,"../WebGL/webglSquare.js":63,"ngraph.events":6,"ngraph.merge":27}],53:[function(require,module,exports){ +},{"../Input/webglInputManager.js":37,"../WebGL/webglLine.js":59,"../WebGL/webglLinkProgram.js":60,"../WebGL/webglNodeProgram.js":61,"../WebGL/webglSquare.js":62,"ngraph.events":6,"ngraph.merge":25}],52:[function(require,module,exports){ module.exports = parseColor; function parseColor(color) { @@ -5470,7 +5511,7 @@ function parseColor(color) { return parsedColor; } -},{}],54:[function(require,module,exports){ +},{}],53:[function(require,module,exports){ module.exports = Texture; /** @@ -5483,7 +5524,7 @@ function Texture(size) { this.canvas.width = this.canvas.height = size; } -},{}],55:[function(require,module,exports){ +},{}],54:[function(require,module,exports){ /** * @fileOverview Utility functions for webgl rendering. * @@ -5587,7 +5628,7 @@ function webgl(gl) { }; } -},{}],56:[function(require,module,exports){ +},{}],55:[function(require,module,exports){ var Texture = require('./texture.js'); module.exports = webglAtlas; @@ -5770,7 +5811,7 @@ function webglAtlas(tilesPerTexture) { return that; } -},{"./texture.js":54}],57:[function(require,module,exports){ +},{"./texture.js":53}],56:[function(require,module,exports){ module.exports = webglImage; /** @@ -5802,7 +5843,7 @@ function webglImage(size, src) { }; } -},{}],58:[function(require,module,exports){ +},{}],57:[function(require,module,exports){ /** * @fileOverview Defines an image nodes for webglGraphics class. * Shape of nodes is square. @@ -6041,7 +6082,7 @@ function webglImageNodeProgram() { }; } -},{"./webgl.js":55,"./webglAtlas.js":56}],59:[function(require,module,exports){ +},{"./webgl.js":54,"./webglAtlas.js":55}],58:[function(require,module,exports){ var documentEvents = require('../Utils/documentEvents.js'); module.exports = webglInputEvents; @@ -6107,6 +6148,7 @@ function webglInputEvents(webglGraphics) { startListen = function (root) { var pos = {x : 0, y : 0}, lastFound = null, + lastUpdate = 1, lastClickTime = +new Date(), handleMouseMove = function (e) { @@ -6125,7 +6167,7 @@ function webglInputEvents(webglGraphics) { }; window.addEventListener('resize', updateBoundRect); - setTimeout(updateBoundRect, 0); + updateBoundRect(); // mouse move inside container serves only to track mouse enter/leave events. root.addEventListener('mousemove', @@ -6133,7 +6175,12 @@ function webglInputEvents(webglGraphics) { if (mouseCapturedNode) { return; } - + if (lastUpdate++ % 7 === 0) { + // since there is no bullet proof method to detect resize + // event, we preemptively update the bounding rectangle + updateBoundRect(); + lastUpdate = 1; + } var cancelBubble = false, node; @@ -6157,7 +6204,7 @@ function webglInputEvents(webglGraphics) { function (e) { var cancelBubble = false, args; - + updateBoundRect(); pos.x = e.clientX - boundRect.left; pos.y = e.clientY - boundRect.top; @@ -6263,7 +6310,7 @@ function webglInputEvents(webglGraphics) { return webglGraphics.webglInputEvents; } -},{"../Utils/documentEvents.js":42}],60:[function(require,module,exports){ +},{"../Utils/documentEvents.js":41}],59:[function(require,module,exports){ var parseColor = require('./parseColor.js'); module.exports = webglLine; @@ -6284,7 +6331,7 @@ function webglLine(color) { }; } -},{"./parseColor.js":53}],61:[function(require,module,exports){ +},{"./parseColor.js":52}],60:[function(require,module,exports){ /** * @fileOverview Defines a naive form of links for webglGraphics class. * This form allows to change color of links. @@ -6442,7 +6489,7 @@ function webglLinkProgram() { }; } -},{"./webgl.js":55}],62:[function(require,module,exports){ +},{"./webgl.js":54}],61:[function(require,module,exports){ /** * @fileOverview Defines a naive form of nodes for webglGraphics class. * This form allows to change color of node. Shape of nodes is rectangular. @@ -6590,7 +6637,7 @@ function webglNodeProgram() { }; } -},{"./webgl.js":55}],63:[function(require,module,exports){ +},{"./webgl.js":54}],62:[function(require,module,exports){ var parseColor = require('./parseColor.js'); module.exports = webglSquare; @@ -6616,9 +6663,8 @@ function webglSquare(size, color) { }; } -},{"./parseColor.js":53}],64:[function(require,module,exports){ - -module.exports = '0.7.0.alpha'; +},{"./parseColor.js":52}],63:[function(require,module,exports){ +module.exports = '0.7.0'; },{}]},{},[1])(1) }); \ No newline at end of file diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 972a6c9..01a41b8 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,s){if(!t[a]){if(!n[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=s-i,d=o-a,p=a*i-o*s,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=u*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-u*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=t},{}],3:[function(e,n){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n){function t(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){u=e.id,s(u),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function g(e){var n=w[e];n.mass=y(e)}function h(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function m(e){var n=w[e];return n||(c(e),n=w[e]),n}function y(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var x=e("ngraph.physics.simulator");t=t||x(),o(t,"physicsSimulator").has("step","getBestNewBodyPosition","addBodyAt");var w="function"==typeof Object.create?Object.create(null):{},b={},E=t.settings.springTransform||r;f(),s();var L={step:function(){return t.step()},getNodePosition:function(e){return m(e).pos},setNodePosition:function(e){var n=m(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return t.getBBox()},pinNode:function(e,n){var t=m(e.id);t.isPinned=!!n},isNodePinned:function(e){return m(e.id).isPinned},dispose:function(){n.off("changed",u)},getBody:a,getSpring:i,simulator:t};return L}function r(){}n.exports=t,n.exports.simulator=e("ngraph.physics.simulator");var o=e("varta")},{"ngraph.physics.simulator":8,varta:23}],8:[function(e,n){function t(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.force.reset(),v.updateBodyForce(e),m.update(e);for(n=p.length;n--;)h.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),s=n.createBounds||e("./lib/bounds"),u=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),g=s(l,n),h=f(n),m=u(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return g.update(),en))return l.splice(n,1),0===l.length&&g.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return g.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=t},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":16,"ngraph.quadtreebh":18}],9:[function(e,n){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var s=n[e];s.isPinned?(s.pos.x=s.prevPos.x,s.pos.y=s.prevPos.y):(s.prevPos.x=s.pos.x,s.prevPos.y=s.pos.y),s.pos.xo&&(o=s.pos.x),s.pos.ya&&(a=s.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var s=0;st;++t){var u=e[t],f=n/u.mass;u.velocity.x+=f*u.force.x,u.velocity.y+=f*u.force.y;var c=u.velocity.x,d=u.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(u.velocity.x=c/l,u.velocity.y=d/l),r=n*u.velocity.x,i=n*u.velocity.y,u.pos.x+=r,u.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=t},{}],13:[function(e,n){function t(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=t},{}],14:[function(e,n){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,s=o.pos.y-t.pos.y,u=Math.sqrt(a*a+s*s);0===u&&(a=(r.nextDouble()-.5)/50,s=(r.nextDouble()-.5)/50,u=Math.sqrt(a*a+s*s));var f=u-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/u*e.weight;t.force.x+=c*a,t.force.y+=c*s,o.force.x-=c*a,o.force.y-=c*s}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":16,"ngraph.random":22}],15:[function(e,n){function t(e,n,t){var o="[object Array]"===Object.prototype.toString.call(t);if(o)for(var i=0;i0&&i(a.pos,o.pos));if(0===s&&i(a.pos,o.pos))return}u.push(r,a),u.push(r,o)}else{var v=o.pos.x,g=o.pos.y;r.mass=r.mass+o.mass,r.massX=r.massX+o.mass*v,r.massY=r.massY+o.mass*g;var h=0,m=r.left,y=(r.right+m)/2,x=r.top,w=(r.bottom+x)/2;if(v>y){h+=1;var b=m;m=y,y+=y-b}if(g>w){h+=2;var E=x;x=w,w+=w-E}var L=r.quads[h];L?u.push(L,o):(L=l(),L.left=m,L.top=x,L.right=y,L.bottom=w,L.body=o,r.quads[h]=L)}}},g=function(e){var n,r,o,i,u=s,c=0,d=0,l=1,v=0,g=1;for(u[0]=p;l;){var h=u[v],m=h.body;l-=1,v+=1,m&&m!==e?(r=m.pos.x-e.pos.x,o=m.pos.y-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),n=a*m.mass*e.mass/(i*i*i),c+=n*r,d+=n*o):(r=h.massX/h.mass-e.pos.x,o=h.massY/h.mass-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),(h.right-h.left)/is&&(t=s),s>o&&(o=s),r>u&&(r=u),u>i&&(i=u)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,d=0,p=l(),p.left=t,p.right=o,p.top=r,p.bottom=i,n=a-1,n>0&&(p.body=e[n]);n--;)v(e[n],p)};return{insertBodies:h,updateBodyForce:g,options:function(e){return e?("number"==typeof e.gravity&&(a=e.gravity),"number"==typeof e.theta&&(f=e.theta),this):{gravity:a,theta:f}}}}},{"./insertStack":19,"./isSamePosition":20,"./node":21,"ngraph.random":22}],19:[function(e,n){function t(){this.stack=[],this.popIdx=0}function r(e,n){this.node=e,this.body=n}n.exports=t,t.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new r(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],20:[function(e,n){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],21:[function(e,n){n.exports=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],22:[function(e,n){function t(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function r(e,n){var r=n||t();if("function"!=typeof r.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var t,o,i;for(t=e.length-1;t>0;--t)o=r.next(t+1),i=e[o],e[o]=e[t],e[t]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,t,o;for(n=e.length-1;n>0;--n)t=r.next(n+1),o=e[t],e[t]=e[n],e[n]=o;return e}}}n.exports={random:t,randomIterator:r}},{}],23:[function(e,n){function t(e,n){function t(){return o(e,n,arguments)}return n=n||"Argument",{has:t}}function r(){function e(e,t){return o(e,t,n)}var n=arguments;return e}function o(e,n,t){if(void 0===e)throw new Error(n+" is not defined");for(var r=0;re)throw new Error("Invalid number of nodes");var n,t=l();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function r(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=t(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function o(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=l();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function i(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=l();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function a(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=l();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function s(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=l();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function u(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=l();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var s=i*e*n,u=r+o*e+s;r>0&&a.addLink(u,r-1+o*e+s),o>0&&a.addLink(u,r+(o-1)*e+s),i>0&&a.addLink(u,r+o*e+(i-1)*e*n)}return a}function f(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=l(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function c(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=l();for(n=0;e>n;++n)t.addNode(n);return t}function d(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,s=e("ngraph.random").random(o||42),u=l();for(i=0;n>i;++i)u.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,u.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(s.nextDouble()n)return!1;S(),P.splice(n,1);var t=u(e.fromId),o=u(e.toId);return t&&(n=r(e,t.links),n>=0&&t.links.splice(n,1)),o&&(n=r(e,o.links),n>=0&&o.links.splice(n,1)),T(e,"remove"),D(),!0}function p(e,n){var t,r=u(e);if(!r)return null;for(t=0;tn;++n)e(P[n])}function h(e,n,t){var r,o,i,a=u(e);if(a&&a.links&&"function"==typeof n)if(t)for(r=0;r0&&(M.fire("changed",I),I.length=0)}function w(){return Object.keys?b:E}function b(e){if("function"==typeof e)for(var n=Object.keys(L),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function o(e){this.id=e,this.links=[],this.data=null}function i(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=t;var a=e("ngraph.events")},{"ngraph.events":6}],27:[function(e,n,t){arguments[4][16][0].apply(t,arguments)},{dup:16}],28:[function(e,n,t){arguments[4][22][0].apply(t,arguments)},{dup:22}],29:[function(e,n){function t(e,n,t){function r(e){s.nodes.push(u(e))}function o(e){s.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var s={nodes:[],links:[]},u=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(s)}n.exports=t},{}],30:[function(e,n){function t(e,n){var t=r(e);if(void 0===n)return t;for(var o=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),s(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},k=function(e){p=!1,r.off("touchmove",A),r.off("touchend",k),r.off("touchcancel",k),c=null,a&&a(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,r.on("touchmove",A),r.on("touchend",k),r.on("touchcancel",k))},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return a=e,this -},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),r.off("mousemove",w),r.off("mouseup",E),r.off("touchmove",A),r.off("touchend",k),r.off("touchcancel",k),P(null)}}}n.exports=t;var r=e("../Utils/documentEvents.js"),o=e("../Utils/browserInfo.js"),i=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":41,"../Utils/documentEvents.js":42,"../Utils/findElementPosition.js":43}],39:[function(e,n){function t(e,n){var t=r(n),o=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){o=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(o);var r=i[e.id];return r&&r.onStart&&r.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(o),o=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(o){var t=i[o.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=t;var r=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":59}],40:[function(e,n){function t(e,n){function t(e){return d[e]}n=r(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var a=o(n.seed),s=new i(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),u={},f=function(){return{x:a.next(n.maxX),y:a.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],s)},p=function(){0!==e.getNodesCount()&&(s.x1=Number.MAX_VALUE,s.y1=Number.MAX_VALUE,s.x2=Number.MIN_VALUE,s.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){u[e.id]=e},g=function(e){for(var n=0;n0)for(e=0;en,t)}),e.forEachNode(O),H(),e.on("changed",q)},K=function(){y=!1,H(),W(),a.off("resize",V),j.removeAllListeners(),l.stop(),e.forEachLink(function(e){n.renderLinks&&B(e)}),e.forEachNode(function(e){F(e),R(e)}),v.dispose(),z()};return{run:function(e){return y||(k(),S(),D(),G(),$(),y=!0),T(e),this},reset:function(){g.resetScale(),D(),A.scale=1},pause:function(){P=!0,l.stop()},resume:function(){P=!1,l.restart()},rerender:function(){return _(),this},zoomOut:function(){return J(!0)},zoomIn:function(){return J(!1)},moveTo:function(e,n){g.graphCenterChanged(A.offsetX-e*A.scale,A.offsetY-n*A.scale),_()},getGraphics:function(){return g},dispose:function(){K()},on:function(e,n){return j.addEventListener(e,n),this},off:function(e,n){return j.removeEventListener(e,n),this}}}n.exports=t;var r=e("ngraph.graph"),o=e("ngraph.forcelayout"),i=e("./svgGraphics.js"),a=e("../Utils/windowEvents.js"),s=e("../Input/domInputManager.js"),u=e("../Utils/timer.js"),f=e("../Utils/getDimensions.js"),c=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":37,"../Input/dragndrop.js":38,"../Utils/getDimensions.js":44,"../Utils/timer.js":48,"../Utils/windowEvents.js":49,"./svgGraphics.js":51,"ngraph.forcelayout":7,"ngraph.graph":26}],51:[function(e,n){function t(){function e(){var e=r("svg");return n=r("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,a,s,u,f=1,c={},d={},l=function(){return r("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(){return r("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+a+","+s+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){a=e,s=n,w()},inputManager:i,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var s="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",s)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),u=n.getCTM().multiply(i);f=u.a,a=u.e,s=u.f;var c="matrix("+u.a+", 0, 0,"+u.d+","+u.e+","+u.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof u&&u(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):u=e),t},getSvgRoot:function(){return t}};return o(b),b}n.exports=t;var r=e("simplesvg"),o=e("ngraph.events"),i=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":37,"ngraph.events":6,simplesvg:30}],52:[function(e,n){function t(e){e=f(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,c,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=o(),P=i(),N=function(){return a()},A=function(){return s(3014898687)},k=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),c&&c.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(A=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:r,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,k()},addLink:function(e,n){var t=m++,r=A(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],k()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,k(),I(this),y[0]},resetScale:function(){return j(),c&&(_(),k()),this},init:function(r){var o={};if(e.preserveDrawingBuffer&&(o.preserveDrawingBuffer=!0),n=r,_(),j(),n.appendChild(t),c=t.getContext("experimental-webgl",o),!c){var i="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(i),i}if(e.enableBlending&&(c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA),c.enable(c.BLEND)),e.clearColor){var a=e.clearColorValue;c.clearColor(a.r,a.g,a.b,a.a),this.beginRender=function(){c.clear(c.COLOR_BUFFER_BIT)}}L.load(c),L.updateSize(d/2,l/2),P.load(c),P.updateSize(d/2,l/2),k(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!c&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!c&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return u(T),T}n.exports=t;var r=e("../Input/webglInputManager.js"),o=e("../WebGL/webglLinkProgram.js"),i=e("../WebGL/webglNodeProgram.js"),a=e("../WebGL/webglSquare.js"),s=e("../WebGL/webglLine.js"),u=e("ngraph.events"),f=e("ngraph.merge")},{"../Input/webglInputManager.js":39,"../WebGL/webglLine.js":60,"../WebGL/webglLinkProgram.js":61,"../WebGL/webglNodeProgram.js":62,"../WebGL/webglSquare.js":63,"ngraph.events":6,"ngraph.merge":27}],53:[function(e,n){function t(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=t},{}],54:[function(e,n){function t(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=t},{}],55:[function(e,n){function t(e){var n=function(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r};return{createProgram:function(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var s=e.getShaderInfoLog(o);throw window.alert(s),s}return o},extendArray:function(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e},copyArrayPart:function(e,n,t,r){var o;for(o=0;r>o;++o)e[n+o]=e[t+o]},swapArrayPart:function(e,n,t,r){var o;for(o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}},getLocations:function(n,t){var r,o={};for(r=0;r10?v():n=window.setTimeout(v,400)},h=function(e,n){var t=f[e.textureNumber].canvas,r=f[n.textureNumber].ctx,o=n.col*i,a=n.row*i;r.drawImage(t,e.col*i,e.row*i,i,i,o,a,i,i),f[e.textureNumber].isDirty=!0,f[n.textureNumber].isDirty=!0},m=function(e,n,t){var r=p(e),o={offset:e};r.textureNumber>=f.length&&l();var a=f[r.textureNumber];a.ctx.drawImage(n,r.col*i,r.row*i,i,i),c[e]=n.src,s[n.src]=o,a.isDirty=!0,t(o)};if(!d(e))throw"Tiles per texture should be power of two.";return t={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;e0&&(h-=1),n.id0&&(n.src&&e.remove(n.src),a.copyArrayPart(m,n.id*l,h*l,l))},replaceProperties:function(e,n){n._offset=e._offset},updateTransform:function(e){d=!0,c=e},updateSize:function(e,n){u=e,f=n,d=!0},render:function(){t.useProgram(n),t.bindBuffer(t.ARRAY_BUFFER,i),t.bufferData(t.ARRAY_BUFFER,m,t.DYNAMIC_DRAW),d&&(d=!1,t.uniformMatrix4fv(s.transform,!1,c),t.uniform2f(s.screenSize,u,f)),t.vertexAttribPointer(s.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(s.customAttributes,1,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),x(),t.drawArrays(t.TRIANGLES,0,6*h)}}}var r=e("./webglAtlas.js"),o=e("./webgl.js");n.exports=t},{"./webgl.js":55,"./webglAtlas.js":56}],59:[function(e,n){function t(e){if(e.webglInputEvents)return e.webglInputEvents;var n,t,o=function(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oa-y&&r[0]===m?h(p,r):h(l,r),y=a,h(c,r)&&v(e))})};return e.getGraphicsRoot(m),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&s.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&f.push(e),this},mouseUp:function(e){return"function"==typeof e&&c.push(e),this},mouseMove:function(e){return"function"==typeof e&&d.push(e),this},click:function(e){return"function"==typeof e&&l.push(e),this},dblClick:function(e){return"function"==typeof e&&p.push(e),this},mouseCapture:function(e){a=e},releaseMouseCapture:function(){a=null}},e.webglInputEvents}var r=e("../Utils/documentEvents.js");n.exports=t},{"../Utils/documentEvents.js":42}],60:[function(e,n){function t(e){return{color:r(e)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":53}],61:[function(e,n){function t(){var e,n,t,o,i,a,s,u,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,o=r(a),e=o.createProgram(v,p),n.useProgram(e),i=o.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&o.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){s=e,u=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,s,u)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&o.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":55}],62:[function(e,n){function t(){var e,n,t,o,i,a,s,u,f,c=4,d=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),p=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),v=new ArrayBuffer(16*d),g=new Float32Array(v),h=new Uint32Array(v),m=0,y=function(){if((m+1)*d>=v.byteLength){var e=new ArrayBuffer(2*v.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(h),g=n,h=t,v=e}};return{load:function(a){n=a,i=r(a),e=i.createProgram(p,l),n.useProgram(e),o=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.color),t=n.createBuffer()},position:function(e,n){var t=e.id;g[t*c]=n.x,g[t*c+1]=n.y,g[t*c+2]=e.size,h[t*c+3]=e.color},updateTransform:function(e){f=!0,u=e},updateSize:function(e,n){a=e,s=n,f=!0},removeNode:function(e){m>0&&(m-=1),e.id0&&i.copyArrayPart(h,e.id*c,m*c,c)},createNode:function(){y(),m+=1},replaceProperties:function(){},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,v,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,u),n.uniform2f(o.screenSize,a,s)),n.vertexAttribPointer(o.vertexPos,3,n.FLOAT,!1,c*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.color,4,n.UNSIGNED_BYTE,!0,c*Float32Array.BYTES_PER_ELEMENT,12),n.drawArrays(n.POINTS,0,m)}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":55}],63:[function(e,n){function t(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":53}],64:[function(e,n){n.exports="0.7.0.alpha"},{}]},{},[1])(1)}); \ No newline at end of file +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,s){if(!t[a]){if(!n[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=s-i,d=o-a,p=a*i-o*s,v=f*e+d*n+p,h=f*t+d*r+p,0!==v&&0!==h&&v>=0==h>=0?null:(y=u*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-u*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=t},{}],3:[function(e,n){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n){function t(e,n){function t(e){h[e]/=2}function r(e){h[e.id]=0}function o(e){u=e.id,s(u),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function h(e){var n=w[e];n.mass=y(e)}function g(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function m(e){var n=w[e];return n||(c(e),n=w[e]),n}function y(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var x=e("ngraph.physics.simulator");t=t||x(),o(t,"physicsSimulator").has("step","getBestNewBodyPosition","addBodyAt");var w="function"==typeof Object.create?Object.create(null):{},b={},E=t.settings.springTransform||r;f(),s();var L={step:function(){return t.step()},getNodePosition:function(e){return m(e).pos},setNodePosition:function(e){var n=m(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return t.getBBox()},pinNode:function(e,n){var t=m(e.id);t.isPinned=!!n},isNodePinned:function(e){return m(e.id).isPinned},dispose:function(){n.off("changed",u)},getBody:a,getSpring:i,simulator:t};return L}function r(){}n.exports=t,n.exports.simulator=e("ngraph.physics.simulator");var o=e("varta")},{"ngraph.physics.simulator":8,varta:21}],8:[function(e,n){function t(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.force.reset(),v.updateBodyForce(e),m.update(e);for(n=p.length;n--;)g.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),s=n.createBounds||e("./lib/bounds"),u=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),h=s(l,n),g=f(n),m=u(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return h.update(),en))return l.splice(n,1),0===l.length&&h.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return h.getBestNewPosition(e)},getBBox:function(){return h.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=t},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":25,"ngraph.quadtreebh":17}],9:[function(e,n){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var s=n[e];s.isPinned?(s.pos.x=s.prevPos.x,s.pos.y=s.prevPos.y):(s.prevPos.x=s.pos.x,s.prevPos.y=s.pos.y),s.pos.xo&&(o=s.pos.x),s.pos.ya&&(a=s.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var s=0;st;++t){var u=e[t],f=n/u.mass;u.velocity.x+=f*u.force.x,u.velocity.y+=f*u.force.y;var c=u.velocity.x,d=u.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(u.velocity.x=c/l,u.velocity.y=d/l),r=n*u.velocity.x,i=n*u.velocity.y,u.pos.x+=r,u.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=t},{}],13:[function(e,n){function t(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=t},{}],14:[function(e,n){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,s=o.pos.y-t.pos.y,u=Math.sqrt(a*a+s*s);0===u&&(a=(r.nextDouble()-.5)/50,s=(r.nextDouble()-.5)/50,u=Math.sqrt(a*a+s*s));var f=u-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/u*e.weight;t.force.x+=c*a,t.force.y+=c*s,o.force.x-=c*a,o.force.y-=c*s}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":25,"ngraph.random":26}],15:[function(e,n){function t(e,n,t){var o="[object Array]"===Object.prototype.toString.call(t);if(o)for(var i=0;i0&&i(a.pos,o.pos));if(0===s&&i(a.pos,o.pos))return}u.push(r,a),u.push(r,o)}else{var v=o.pos.x,h=o.pos.y;r.mass=r.mass+o.mass,r.massX=r.massX+o.mass*v,r.massY=r.massY+o.mass*h;var g=0,m=r.left,y=(r.right+m)/2,x=r.top,w=(r.bottom+x)/2;if(v>y){g+=1;var b=m;m=y,y+=y-b}if(h>w){g+=2;var E=x;x=w,w+=w-E}var L=r.quads[g];L?u.push(L,o):(L=l(),L.left=m,L.top=x,L.right=y,L.bottom=w,L.body=o,r.quads[g]=L)}}},h=function(e){var n,r,o,i,u=s,c=0,d=0,l=1,v=0,h=1;for(u[0]=p;l;){var g=u[v],m=g.body;l-=1,v+=1,m&&m!==e?(r=m.pos.x-e.pos.x,o=m.pos.y-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),n=a*m.mass*e.mass/(i*i*i),c+=n*r,d+=n*o):(r=g.massX/g.mass-e.pos.x,o=g.massY/g.mass-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),(g.right-g.left)/is&&(t=s),s>o&&(o=s),r>u&&(r=u),u>i&&(i=u)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,d=0,p=l(),p.left=t,p.right=o,p.top=r,p.bottom=i,n=a-1,n>0&&(p.body=e[n]);n--;)v(e[n],p)};return{insertBodies:g,updateBodyForce:h,options:function(e){return e?("number"==typeof e.gravity&&(a=e.gravity),"number"==typeof e.theta&&(f=e.theta),this):{gravity:a,theta:f}}}}},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":26}],18:[function(e,n){function t(){this.stack=[],this.popIdx=0}function r(e,n){this.node=e,this.body=n}n.exports=t,t.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new r(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],19:[function(e,n){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],20:[function(e,n){n.exports=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],21:[function(e,n){function t(e,n){function t(){return o(e,n,arguments)}return n=n||"Argument",{has:t}}function r(){function e(e,t){return o(e,t,n)}var n=arguments;return e}function o(e,n,t){if(void 0===e)throw new Error(n+" is not defined");for(var r=0;re)throw new Error("Invalid number of nodes");var n,t=l();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function r(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=t(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function o(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=l();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function i(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=l();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function a(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=l();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function s(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=l();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function u(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=l();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var s=i*e*n,u=r+o*e+s;r>0&&a.addLink(u,r-1+o*e+s),o>0&&a.addLink(u,r+(o-1)*e+s),i>0&&a.addLink(u,r+o*e+(i-1)*e*n)}return a}function f(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=l(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function c(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=l();for(n=0;e>n;++n)t.addNode(n);return t}function d(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,s=e("ngraph.random").random(o||42),u=l();for(i=0;n>i;++i)u.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,u.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(s.nextDouble()n)return!1;S(),P.splice(n,1);var t=u(e.fromId),o=u(e.toId);return t&&(n=r(e,t.links),n>=0&&t.links.splice(n,1)),o&&(n=r(e,o.links),n>=0&&o.links.splice(n,1)),T(e,"remove"),D(),!0}function p(e,n){var t,r=u(e);if(!r)return null;for(t=0;tn;++n)e(P[n])}function g(e,n,t){var r,o,i,a=u(e);if(a&&a.links&&"function"==typeof n)if(t)for(r=0;r0&&(M.fire("changed",I),I.length=0)}function w(){return Object.keys?b:E}function b(e){if("function"==typeof e)for(var n=Object.keys(L),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function o(e){this.id=e,this.links=[],this.data=null}function i(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=t;var a=e("ngraph.events")},{"ngraph.events":6}],25:[function(e,n){function t(e,n){var r;if(e||(e={}),n)for(r in n)if(n.hasOwnProperty(r)){var o=e.hasOwnProperty(r),i=typeof n[r],a=!o||typeof e[r]!==i;a?e[r]=n[r]:"object"===i&&(e[r]=t(e[r],n[r]))}return e}n.exports=t},{}],26:[function(e,n){function t(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function r(e,n){var r=n||t();if("function"!=typeof r.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var t,o,i;for(t=e.length-1;t>0;--t)o=r.next(t+1),i=e[o],e[o]=e[t],e[t]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,t,o;for(n=e.length-1;n>0;--n)t=r.next(n+1),o=e[t],e[t]=e[n],e[n]=o;return e}}}n.exports={random:t,randomIterator:r}},{}],27:[function(e,n){function t(e,n,t){function r(e){s.nodes.push(u(e))}function o(e){s.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var s={nodes:[],links:[]},u=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(s)}n.exports=t},{}],28:[function(e,n){function t(e,n){var t=r(e);if(void 0===n)return t;for(var o=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),s(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},k=function(e){p=!1,r.off("touchmove",A),r.off("touchend",k),r.off("touchcancel",k),c=null,a&&a(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,r.on("touchmove",A),r.on("touchend",k),r.on("touchcancel",k))},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return a=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),r.off("mousemove",w),r.off("mouseup",E),r.off("touchmove",A),r.off("touchend",k),r.off("touchcancel",k),P(null) +}}}n.exports=t;var r=e("../Utils/documentEvents.js"),o=e("../Utils/browserInfo.js"),i=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":40,"../Utils/documentEvents.js":41,"../Utils/findElementPosition.js":42}],37:[function(e,n){function t(e,n){var t=r(n),o=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){o=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(o);var r=i[e.id];return r&&r.onStart&&r.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(o),o=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(o){var t=i[o.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=t;var r=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":58}],38:[function(e,n){function t(e,n){function t(e){return d[e]}n=r(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var a=o(n.seed),s=new i(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),u={},f=function(){return{x:a.next(n.maxX),y:a.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],s)},p=function(){0!==e.getNodesCount()&&(s.x1=Number.MAX_VALUE,s.y1=Number.MAX_VALUE,s.x2=Number.MIN_VALUE,s.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){u[e.id]=e},h=function(e){for(var n=0;n0)for(e=0;en,t)}),e.forEachNode(O),H(),e.on("changed",q)},K=function(){y=!1,H(),W(),a.off("resize",V),j.removeAllListeners(),l.stop(),e.forEachLink(function(e){n.renderLinks&&B(e)}),e.forEachNode(function(e){F(e),U(e)}),v.dispose(),z()};return{run:function(e){return y||(k(),S(),D(),G(),$(),y=!0),T(e),this},reset:function(){h.resetScale(),D(),A.scale=1},pause:function(){P=!0,l.stop()},resume:function(){P=!1,l.restart()},rerender:function(){return _(),this},zoomOut:function(){return J(!0)},zoomIn:function(){return J(!1)},moveTo:function(e,n){h.graphCenterChanged(A.offsetX-e*A.scale,A.offsetY-n*A.scale),_()},getGraphics:function(){return h},dispose:function(){K()},on:function(e,n){return j.addEventListener(e,n),this},off:function(e,n){return j.removeEventListener(e,n),this}}}n.exports=t;var r=e("ngraph.graph"),o=e("ngraph.forcelayout"),i=e("./svgGraphics.js"),a=e("../Utils/windowEvents.js"),s=e("../Input/domInputManager.js"),u=e("../Utils/timer.js"),f=e("../Utils/getDimensions.js"),c=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.forcelayout":7,"ngraph.graph":24}],50:[function(e,n){function t(){function e(){var e=r("svg");return n=r("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,a,s,u,f=1,c={},d={},l=function(){return r("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(){return r("line").attr("stroke","#999")},h=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},g=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+a+","+s+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return h=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){a=e,s=n,w()},inputManager:i,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var s="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",s)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),u=n.getCTM().multiply(i);f=u.a,a=u.e,s=u.f;var c="matrix("+u.a+", 0, 0,"+u.d+","+u.e+","+u.f+")";return n.attr("transform",c),g(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),g(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof u&&u(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,h(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):u=e),t},getSvgRoot:function(){return t}};return o(b),b}n.exports=t;var r=e("simplesvg"),o=e("ngraph.events"),i=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":35,"ngraph.events":6,simplesvg:28}],51:[function(e,n){function t(e){e=f(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,c,d,l,p,v,h,g=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=o(),P=i(),N=function(){return a()},A=function(){return s(3014898687)},k=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),c&&c.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(A=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:r,beginRender:function(){},endRender:function(){m>0&&L.render(),g>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,k()},addLink:function(e,n){var t=m++,r=A(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=g++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],k()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,k(),I(this),y[0]},resetScale:function(){return j(),c&&(_(),k()),this},init:function(r){var o={};if(e.preserveDrawingBuffer&&(o.preserveDrawingBuffer=!0),n=r,_(),j(),n.appendChild(t),c=t.getContext("experimental-webgl",o),!c){var i="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(i),i}if(e.enableBlending&&(c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA),c.enable(c.BLEND)),e.clearColor){var a=e.clearColorValue;c.clearColor(a.r,a.g,a.b,a.a),this.beginRender=function(){c.clear(c.COLOR_BUFFER_BIT)}}L.load(c),L.updateSize(d/2,l/2),P.load(c),P.updateSize(d/2,l/2),k(),"function"==typeof h&&h(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){g>0&&(g-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(g>t){if(0===g||g===t)return;var r=x[g];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;g>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):h=e),t},setNodeProgram:function(e){if(!c&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!c&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;g>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return u(T),T}n.exports=t;var r=e("../Input/webglInputManager.js"),o=e("../WebGL/webglLinkProgram.js"),i=e("../WebGL/webglNodeProgram.js"),a=e("../WebGL/webglSquare.js"),s=e("../WebGL/webglLine.js"),u=e("ngraph.events"),f=e("ngraph.merge")},{"../Input/webglInputManager.js":37,"../WebGL/webglLine.js":59,"../WebGL/webglLinkProgram.js":60,"../WebGL/webglNodeProgram.js":61,"../WebGL/webglSquare.js":62,"ngraph.events":6,"ngraph.merge":25}],52:[function(e,n){function t(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=t},{}],53:[function(e,n){function t(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=t},{}],54:[function(e,n){function t(e){var n=function(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r};return{createProgram:function(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var s=e.getShaderInfoLog(o);throw window.alert(s),s}return o},extendArray:function(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e},copyArrayPart:function(e,n,t,r){var o;for(o=0;r>o;++o)e[n+o]=e[t+o]},swapArrayPart:function(e,n,t,r){var o;for(o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}},getLocations:function(n,t){var r,o={};for(r=0;r10?v():n=window.setTimeout(v,400)},g=function(e,n){var t=f[e.textureNumber].canvas,r=f[n.textureNumber].ctx,o=n.col*i,a=n.row*i;r.drawImage(t,e.col*i,e.row*i,i,i,o,a,i,i),f[e.textureNumber].isDirty=!0,f[n.textureNumber].isDirty=!0},m=function(e,n,t){var r=p(e),o={offset:e};r.textureNumber>=f.length&&l();var a=f[r.textureNumber];a.ctx.drawImage(n,r.col*i,r.row*i,i,i),c[e]=n.src,s[n.src]=o,a.isDirty=!0,t(o)};if(!d(e))throw"Tiles per texture should be power of two.";return t={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;e0&&(g-=1),n.id0&&(n.src&&e.remove(n.src),a.copyArrayPart(m,n.id*l,g*l,l))},replaceProperties:function(e,n){n._offset=e._offset},updateTransform:function(e){d=!0,c=e},updateSize:function(e,n){u=e,f=n,d=!0},render:function(){t.useProgram(n),t.bindBuffer(t.ARRAY_BUFFER,i),t.bufferData(t.ARRAY_BUFFER,m,t.DYNAMIC_DRAW),d&&(d=!1,t.uniformMatrix4fv(s.transform,!1,c),t.uniform2f(s.screenSize,u,f)),t.vertexAttribPointer(s.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(s.customAttributes,1,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),x(),t.drawArrays(t.TRIANGLES,0,6*g)}}}var r=e("./webglAtlas.js"),o=e("./webgl.js");n.exports=t},{"./webgl.js":54,"./webglAtlas.js":55}],58:[function(e,n){function t(e){if(e.webglInputEvents)return e.webglInputEvents;var n,t,o=function(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oa-x&&r[0]===m?g(p,r):g(l,r),x=a,g(c,r)&&v(e))})};return e.getGraphicsRoot(m),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&s.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&f.push(e),this},mouseUp:function(e){return"function"==typeof e&&c.push(e),this},mouseMove:function(e){return"function"==typeof e&&d.push(e),this},click:function(e){return"function"==typeof e&&l.push(e),this},dblClick:function(e){return"function"==typeof e&&p.push(e),this},mouseCapture:function(e){a=e},releaseMouseCapture:function(){a=null}},e.webglInputEvents}var r=e("../Utils/documentEvents.js");n.exports=t},{"../Utils/documentEvents.js":41}],59:[function(e,n){function t(e){return{color:r(e)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],60:[function(e,n){function t(){var e,n,t,o,i,a,s,u,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),h=0,g=new ArrayBuffer(16*l),m=new Float32Array(g),y=new Uint32Array(g),x=function(){if((h+1)*l>g.byteLength){var e=new ArrayBuffer(2*g.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,g=e}};return{load:function(a){n=a,o=r(a),e=o.createProgram(v,p),n.useProgram(e),i=o.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),h+=1,a=e.id},removeLink:function(e){h>0&&(h-=1),e.id0&&o.copyArrayPart(y,e.id*d,h*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){s=e,u=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,g,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,s,u)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*h),a=h-1},bringToFront:function(e){a>e.id&&o.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],61:[function(e,n){function t(){var e,n,t,o,i,a,s,u,f,c=4,d=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),p=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),v=new ArrayBuffer(16*d),h=new Float32Array(v),g=new Uint32Array(v),m=0,y=function(){if((m+1)*d>=v.byteLength){var e=new ArrayBuffer(2*v.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(g),h=n,g=t,v=e}};return{load:function(a){n=a,i=r(a),e=i.createProgram(p,l),n.useProgram(e),o=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.color),t=n.createBuffer()},position:function(e,n){var t=e.id;h[t*c]=n.x,h[t*c+1]=n.y,h[t*c+2]=e.size,g[t*c+3]=e.color},updateTransform:function(e){f=!0,u=e},updateSize:function(e,n){a=e,s=n,f=!0},removeNode:function(e){m>0&&(m-=1),e.id0&&i.copyArrayPart(g,e.id*c,m*c,c)},createNode:function(){y(),m+=1},replaceProperties:function(){},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,v,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,u),n.uniform2f(o.screenSize,a,s)),n.vertexAttribPointer(o.vertexPos,3,n.FLOAT,!1,c*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.color,4,n.UNSIGNED_BYTE,!0,c*Float32Array.BYTES_PER_ELEMENT,12),n.drawArrays(n.POINTS,0,m)}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],62:[function(e,n){function t(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],63:[function(e,n){n.exports="0.7.0"},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/src/version.js b/src/version.js index 7fb0fc0..4ca8809 100644 --- a/src/version.js +++ b/src/version.js @@ -1,2 +1 @@ - -module.exports = '0.7.0.alpha'; +module.exports = '0.7.0'; From 7635e6c30154a842290da9679fa68d68fd58cee3 Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 4 Feb 2015 00:25:38 -0800 Subject: [PATCH 158/276] 0.7.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 421e862..1ce4847 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.6.3", + "version": "0.7.0", "description": "Graph Drawing Library", "main": "dist/vivagraph", "directories": { From c880f3612c754681eabefa5f509bd34777f46e11 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 7 Feb 2015 12:54:39 -0800 Subject: [PATCH 159/276] Updated to latest ngraph.graph --- dist/vivagraph.js | 20 ++++++++++++++++---- dist/vivagraph.min.js | 4 ++-- package.json | 8 ++++---- src/version.js | 2 +- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index c16e771..1162de0 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -2355,10 +2355,22 @@ function createGraph() { /** * Detects whether there is a link between two nodes. * Operation complexity is O(n) where n - number of links of a node. + * NOTE: this function is synonim for getLink() * * @returns link if there is one. null otherwise. */ - hasLink: hasLink + hasLink: getLink, + + /** + * Gets an edge between two nodes. + * Operation complexity is O(n) where n - number of links of a node. + * + * @param {string} fromId link start identifier + * @param {string} toId link end identifier + * + * @returns link if there is one. null otherwise. + */ + getLink: getLink }; // this will add `on()` and `fire()` methods. @@ -2464,7 +2476,7 @@ function createGraph() { var linkId = fromId.toString() + linkConnectionSymbol + toId.toString(); var isMultiEdge = multiEdges.hasOwnProperty(linkId); - if (isMultiEdge || hasLink(fromId, toId)) { + if (isMultiEdge || getLink(fromId, toId)) { if (!isMultiEdge) { multiEdges[linkId] = 0; } @@ -2531,7 +2543,7 @@ function createGraph() { return true; } - function hasLink(fromNodeId, toNodeId) { + function getLink(fromNodeId, toNodeId) { // TODO: Use adjacency matrix to speed up this operation. var node = getNode(fromNodeId), i; @@ -6664,7 +6676,7 @@ function webglSquare(size, color) { } },{"./parseColor.js":52}],63:[function(require,module,exports){ -module.exports = '0.7.0'; +module.exports = '0.7.2'; },{}]},{},[1])(1) }); \ No newline at end of file diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 01a41b8..a5800fe 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,s){if(!t[a]){if(!n[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=s-i,d=o-a,p=a*i-o*s,v=f*e+d*n+p,h=f*t+d*r+p,0!==v&&0!==h&&v>=0==h>=0?null:(y=u*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-u*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=t},{}],3:[function(e,n){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n){function t(e,n){function t(e){h[e]/=2}function r(e){h[e.id]=0}function o(e){u=e.id,s(u),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function h(e){var n=w[e];n.mass=y(e)}function g(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function m(e){var n=w[e];return n||(c(e),n=w[e]),n}function y(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var x=e("ngraph.physics.simulator");t=t||x(),o(t,"physicsSimulator").has("step","getBestNewBodyPosition","addBodyAt");var w="function"==typeof Object.create?Object.create(null):{},b={},E=t.settings.springTransform||r;f(),s();var L={step:function(){return t.step()},getNodePosition:function(e){return m(e).pos},setNodePosition:function(e){var n=m(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return t.getBBox()},pinNode:function(e,n){var t=m(e.id);t.isPinned=!!n},isNodePinned:function(e){return m(e.id).isPinned},dispose:function(){n.off("changed",u)},getBody:a,getSpring:i,simulator:t};return L}function r(){}n.exports=t,n.exports.simulator=e("ngraph.physics.simulator");var o=e("varta")},{"ngraph.physics.simulator":8,varta:21}],8:[function(e,n){function t(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.force.reset(),v.updateBodyForce(e),m.update(e);for(n=p.length;n--;)g.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),s=n.createBounds||e("./lib/bounds"),u=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),h=s(l,n),g=f(n),m=u(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return h.update(),en))return l.splice(n,1),0===l.length&&h.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return h.getBestNewPosition(e)},getBBox:function(){return h.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=t},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":25,"ngraph.quadtreebh":17}],9:[function(e,n){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var s=n[e];s.isPinned?(s.pos.x=s.prevPos.x,s.pos.y=s.prevPos.y):(s.prevPos.x=s.pos.x,s.prevPos.y=s.pos.y),s.pos.xo&&(o=s.pos.x),s.pos.ya&&(a=s.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var s=0;st;++t){var u=e[t],f=n/u.mass;u.velocity.x+=f*u.force.x,u.velocity.y+=f*u.force.y;var c=u.velocity.x,d=u.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(u.velocity.x=c/l,u.velocity.y=d/l),r=n*u.velocity.x,i=n*u.velocity.y,u.pos.x+=r,u.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=t},{}],13:[function(e,n){function t(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=t},{}],14:[function(e,n){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,s=o.pos.y-t.pos.y,u=Math.sqrt(a*a+s*s);0===u&&(a=(r.nextDouble()-.5)/50,s=(r.nextDouble()-.5)/50,u=Math.sqrt(a*a+s*s));var f=u-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/u*e.weight;t.force.x+=c*a,t.force.y+=c*s,o.force.x-=c*a,o.force.y-=c*s}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":25,"ngraph.random":26}],15:[function(e,n){function t(e,n,t){var o="[object Array]"===Object.prototype.toString.call(t);if(o)for(var i=0;i0&&i(a.pos,o.pos));if(0===s&&i(a.pos,o.pos))return}u.push(r,a),u.push(r,o)}else{var v=o.pos.x,h=o.pos.y;r.mass=r.mass+o.mass,r.massX=r.massX+o.mass*v,r.massY=r.massY+o.mass*h;var g=0,m=r.left,y=(r.right+m)/2,x=r.top,w=(r.bottom+x)/2;if(v>y){g+=1;var b=m;m=y,y+=y-b}if(h>w){g+=2;var E=x;x=w,w+=w-E}var L=r.quads[g];L?u.push(L,o):(L=l(),L.left=m,L.top=x,L.right=y,L.bottom=w,L.body=o,r.quads[g]=L)}}},h=function(e){var n,r,o,i,u=s,c=0,d=0,l=1,v=0,h=1;for(u[0]=p;l;){var g=u[v],m=g.body;l-=1,v+=1,m&&m!==e?(r=m.pos.x-e.pos.x,o=m.pos.y-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),n=a*m.mass*e.mass/(i*i*i),c+=n*r,d+=n*o):(r=g.massX/g.mass-e.pos.x,o=g.massY/g.mass-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),(g.right-g.left)/is&&(t=s),s>o&&(o=s),r>u&&(r=u),u>i&&(i=u)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,d=0,p=l(),p.left=t,p.right=o,p.top=r,p.bottom=i,n=a-1,n>0&&(p.body=e[n]);n--;)v(e[n],p)};return{insertBodies:g,updateBodyForce:h,options:function(e){return e?("number"==typeof e.gravity&&(a=e.gravity),"number"==typeof e.theta&&(f=e.theta),this):{gravity:a,theta:f}}}}},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":26}],18:[function(e,n){function t(){this.stack=[],this.popIdx=0}function r(e,n){this.node=e,this.body=n}n.exports=t,t.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new r(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],19:[function(e,n){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],20:[function(e,n){n.exports=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],21:[function(e,n){function t(e,n){function t(){return o(e,n,arguments)}return n=n||"Argument",{has:t}}function r(){function e(e,t){return o(e,t,n)}var n=arguments;return e}function o(e,n,t){if(void 0===e)throw new Error(n+" is not defined");for(var r=0;re)throw new Error("Invalid number of nodes");var n,t=l();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function r(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=t(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function o(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=l();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function i(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=l();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function a(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=l();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function s(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=l();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function u(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=l();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var s=i*e*n,u=r+o*e+s;r>0&&a.addLink(u,r-1+o*e+s),o>0&&a.addLink(u,r+(o-1)*e+s),i>0&&a.addLink(u,r+o*e+(i-1)*e*n)}return a}function f(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=l(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function c(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=l();for(n=0;e>n;++n)t.addNode(n);return t}function d(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,s=e("ngraph.random").random(o||42),u=l();for(i=0;n>i;++i)u.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,u.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(s.nextDouble()n)return!1;S(),P.splice(n,1);var t=u(e.fromId),o=u(e.toId);return t&&(n=r(e,t.links),n>=0&&t.links.splice(n,1)),o&&(n=r(e,o.links),n>=0&&o.links.splice(n,1)),T(e,"remove"),D(),!0}function p(e,n){var t,r=u(e);if(!r)return null;for(t=0;tn;++n)e(P[n])}function g(e,n,t){var r,o,i,a=u(e);if(a&&a.links&&"function"==typeof n)if(t)for(r=0;r0&&(M.fire("changed",I),I.length=0)}function w(){return Object.keys?b:E}function b(e){if("function"==typeof e)for(var n=Object.keys(L),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function o(e){this.id=e,this.links=[],this.data=null}function i(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=t;var a=e("ngraph.events")},{"ngraph.events":6}],25:[function(e,n){function t(e,n){var r;if(e||(e={}),n)for(r in n)if(n.hasOwnProperty(r)){var o=e.hasOwnProperty(r),i=typeof n[r],a=!o||typeof e[r]!==i;a?e[r]=n[r]:"object"===i&&(e[r]=t(e[r],n[r]))}return e}n.exports=t},{}],26:[function(e,n){function t(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function r(e,n){var r=n||t();if("function"!=typeof r.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var t,o,i;for(t=e.length-1;t>0;--t)o=r.next(t+1),i=e[o],e[o]=e[t],e[t]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,t,o;for(n=e.length-1;n>0;--n)t=r.next(n+1),o=e[t],e[t]=e[n],e[n]=o;return e}}}n.exports={random:t,randomIterator:r}},{}],27:[function(e,n){function t(e,n,t){function r(e){s.nodes.push(u(e))}function o(e){s.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var s={nodes:[],links:[]},u=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(s)}n.exports=t},{}],28:[function(e,n){function t(e,n){var t=r(e);if(void 0===n)return t;for(var o=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),s(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},k=function(e){p=!1,r.off("touchmove",A),r.off("touchend",k),r.off("touchcancel",k),c=null,a&&a(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,r.on("touchmove",A),r.on("touchend",k),r.on("touchcancel",k))},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return a=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),r.off("mousemove",w),r.off("mouseup",E),r.off("touchmove",A),r.off("touchend",k),r.off("touchcancel",k),P(null) -}}}n.exports=t;var r=e("../Utils/documentEvents.js"),o=e("../Utils/browserInfo.js"),i=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":40,"../Utils/documentEvents.js":41,"../Utils/findElementPosition.js":42}],37:[function(e,n){function t(e,n){var t=r(n),o=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){o=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(o);var r=i[e.id];return r&&r.onStart&&r.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(o),o=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(o){var t=i[o.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=t;var r=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":58}],38:[function(e,n){function t(e,n){function t(e){return d[e]}n=r(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var a=o(n.seed),s=new i(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),u={},f=function(){return{x:a.next(n.maxX),y:a.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],s)},p=function(){0!==e.getNodesCount()&&(s.x1=Number.MAX_VALUE,s.y1=Number.MAX_VALUE,s.x2=Number.MIN_VALUE,s.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){u[e.id]=e},h=function(e){for(var n=0;n0)for(e=0;en,t)}),e.forEachNode(O),H(),e.on("changed",q)},K=function(){y=!1,H(),W(),a.off("resize",V),j.removeAllListeners(),l.stop(),e.forEachLink(function(e){n.renderLinks&&B(e)}),e.forEachNode(function(e){F(e),U(e)}),v.dispose(),z()};return{run:function(e){return y||(k(),S(),D(),G(),$(),y=!0),T(e),this},reset:function(){h.resetScale(),D(),A.scale=1},pause:function(){P=!0,l.stop()},resume:function(){P=!1,l.restart()},rerender:function(){return _(),this},zoomOut:function(){return J(!0)},zoomIn:function(){return J(!1)},moveTo:function(e,n){h.graphCenterChanged(A.offsetX-e*A.scale,A.offsetY-n*A.scale),_()},getGraphics:function(){return h},dispose:function(){K()},on:function(e,n){return j.addEventListener(e,n),this},off:function(e,n){return j.removeEventListener(e,n),this}}}n.exports=t;var r=e("ngraph.graph"),o=e("ngraph.forcelayout"),i=e("./svgGraphics.js"),a=e("../Utils/windowEvents.js"),s=e("../Input/domInputManager.js"),u=e("../Utils/timer.js"),f=e("../Utils/getDimensions.js"),c=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.forcelayout":7,"ngraph.graph":24}],50:[function(e,n){function t(){function e(){var e=r("svg");return n=r("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,a,s,u,f=1,c={},d={},l=function(){return r("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(){return r("line").attr("stroke","#999")},h=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},g=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+a+","+s+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return h=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){a=e,s=n,w()},inputManager:i,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var s="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",s)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),u=n.getCTM().multiply(i);f=u.a,a=u.e,s=u.f;var c="matrix("+u.a+", 0, 0,"+u.d+","+u.e+","+u.f+")";return n.attr("transform",c),g(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),g(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof u&&u(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,h(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):u=e),t},getSvgRoot:function(){return t}};return o(b),b}n.exports=t;var r=e("simplesvg"),o=e("ngraph.events"),i=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":35,"ngraph.events":6,simplesvg:28}],51:[function(e,n){function t(e){e=f(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,c,d,l,p,v,h,g=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=o(),P=i(),N=function(){return a()},A=function(){return s(3014898687)},k=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),c&&c.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(A=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:r,beginRender:function(){},endRender:function(){m>0&&L.render(),g>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,k()},addLink:function(e,n){var t=m++,r=A(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=g++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],k()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,k(),I(this),y[0]},resetScale:function(){return j(),c&&(_(),k()),this},init:function(r){var o={};if(e.preserveDrawingBuffer&&(o.preserveDrawingBuffer=!0),n=r,_(),j(),n.appendChild(t),c=t.getContext("experimental-webgl",o),!c){var i="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(i),i}if(e.enableBlending&&(c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA),c.enable(c.BLEND)),e.clearColor){var a=e.clearColorValue;c.clearColor(a.r,a.g,a.b,a.a),this.beginRender=function(){c.clear(c.COLOR_BUFFER_BIT)}}L.load(c),L.updateSize(d/2,l/2),P.load(c),P.updateSize(d/2,l/2),k(),"function"==typeof h&&h(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){g>0&&(g-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(g>t){if(0===g||g===t)return;var r=x[g];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;g>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):h=e),t},setNodeProgram:function(e){if(!c&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!c&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;g>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return u(T),T}n.exports=t;var r=e("../Input/webglInputManager.js"),o=e("../WebGL/webglLinkProgram.js"),i=e("../WebGL/webglNodeProgram.js"),a=e("../WebGL/webglSquare.js"),s=e("../WebGL/webglLine.js"),u=e("ngraph.events"),f=e("ngraph.merge")},{"../Input/webglInputManager.js":37,"../WebGL/webglLine.js":59,"../WebGL/webglLinkProgram.js":60,"../WebGL/webglNodeProgram.js":61,"../WebGL/webglSquare.js":62,"ngraph.events":6,"ngraph.merge":25}],52:[function(e,n){function t(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=t},{}],53:[function(e,n){function t(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=t},{}],54:[function(e,n){function t(e){var n=function(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r};return{createProgram:function(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var s=e.getShaderInfoLog(o);throw window.alert(s),s}return o},extendArray:function(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e},copyArrayPart:function(e,n,t,r){var o;for(o=0;r>o;++o)e[n+o]=e[t+o]},swapArrayPart:function(e,n,t,r){var o;for(o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}},getLocations:function(n,t){var r,o={};for(r=0;r10?v():n=window.setTimeout(v,400)},g=function(e,n){var t=f[e.textureNumber].canvas,r=f[n.textureNumber].ctx,o=n.col*i,a=n.row*i;r.drawImage(t,e.col*i,e.row*i,i,i,o,a,i,i),f[e.textureNumber].isDirty=!0,f[n.textureNumber].isDirty=!0},m=function(e,n,t){var r=p(e),o={offset:e};r.textureNumber>=f.length&&l();var a=f[r.textureNumber];a.ctx.drawImage(n,r.col*i,r.row*i,i,i),c[e]=n.src,s[n.src]=o,a.isDirty=!0,t(o)};if(!d(e))throw"Tiles per texture should be power of two.";return t={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;e0&&(g-=1),n.id0&&(n.src&&e.remove(n.src),a.copyArrayPart(m,n.id*l,g*l,l))},replaceProperties:function(e,n){n._offset=e._offset},updateTransform:function(e){d=!0,c=e},updateSize:function(e,n){u=e,f=n,d=!0},render:function(){t.useProgram(n),t.bindBuffer(t.ARRAY_BUFFER,i),t.bufferData(t.ARRAY_BUFFER,m,t.DYNAMIC_DRAW),d&&(d=!1,t.uniformMatrix4fv(s.transform,!1,c),t.uniform2f(s.screenSize,u,f)),t.vertexAttribPointer(s.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(s.customAttributes,1,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),x(),t.drawArrays(t.TRIANGLES,0,6*g)}}}var r=e("./webglAtlas.js"),o=e("./webgl.js");n.exports=t},{"./webgl.js":54,"./webglAtlas.js":55}],58:[function(e,n){function t(e){if(e.webglInputEvents)return e.webglInputEvents;var n,t,o=function(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oa-x&&r[0]===m?g(p,r):g(l,r),x=a,g(c,r)&&v(e))})};return e.getGraphicsRoot(m),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&s.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&f.push(e),this},mouseUp:function(e){return"function"==typeof e&&c.push(e),this},mouseMove:function(e){return"function"==typeof e&&d.push(e),this},click:function(e){return"function"==typeof e&&l.push(e),this},dblClick:function(e){return"function"==typeof e&&p.push(e),this},mouseCapture:function(e){a=e},releaseMouseCapture:function(){a=null}},e.webglInputEvents}var r=e("../Utils/documentEvents.js");n.exports=t},{"../Utils/documentEvents.js":41}],59:[function(e,n){function t(e){return{color:r(e)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],60:[function(e,n){function t(){var e,n,t,o,i,a,s,u,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),h=0,g=new ArrayBuffer(16*l),m=new Float32Array(g),y=new Uint32Array(g),x=function(){if((h+1)*l>g.byteLength){var e=new ArrayBuffer(2*g.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,g=e}};return{load:function(a){n=a,o=r(a),e=o.createProgram(v,p),n.useProgram(e),i=o.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),h+=1,a=e.id},removeLink:function(e){h>0&&(h-=1),e.id0&&o.copyArrayPart(y,e.id*d,h*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){s=e,u=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,g,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,s,u)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*h),a=h-1},bringToFront:function(e){a>e.id&&o.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],61:[function(e,n){function t(){var e,n,t,o,i,a,s,u,f,c=4,d=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),p=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),v=new ArrayBuffer(16*d),h=new Float32Array(v),g=new Uint32Array(v),m=0,y=function(){if((m+1)*d>=v.byteLength){var e=new ArrayBuffer(2*v.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(g),h=n,g=t,v=e}};return{load:function(a){n=a,i=r(a),e=i.createProgram(p,l),n.useProgram(e),o=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.color),t=n.createBuffer()},position:function(e,n){var t=e.id;h[t*c]=n.x,h[t*c+1]=n.y,h[t*c+2]=e.size,g[t*c+3]=e.color},updateTransform:function(e){f=!0,u=e},updateSize:function(e,n){a=e,s=n,f=!0},removeNode:function(e){m>0&&(m-=1),e.id0&&i.copyArrayPart(g,e.id*c,m*c,c)},createNode:function(){y(),m+=1},replaceProperties:function(){},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,v,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,u),n.uniform2f(o.screenSize,a,s)),n.vertexAttribPointer(o.vertexPos,3,n.FLOAT,!1,c*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.color,4,n.UNSIGNED_BYTE,!0,c*Float32Array.BYTES_PER_ELEMENT,12),n.drawArrays(n.POINTS,0,m)}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],62:[function(e,n){function t(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],63:[function(e,n){n.exports="0.7.0"},{}]},{},[1])(1)}); \ No newline at end of file +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,s){if(!t[a]){if(!n[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=s-i,d=o-a,p=a*i-o*s,v=f*e+d*n+p,h=f*t+d*r+p,0!==v&&0!==h&&v>=0==h>=0?null:(y=u*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-u*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=t},{}],3:[function(e,n){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n){function t(e,n){function t(e){h[e]/=2}function r(e){h[e.id]=0}function o(e){u=e.id,s(u),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function h(e){var n=w[e];n.mass=y(e)}function g(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function m(e){var n=w[e];return n||(c(e),n=w[e]),n}function y(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var x=e("ngraph.physics.simulator");t=t||x(),o(t,"physicsSimulator").has("step","getBestNewBodyPosition","addBodyAt");var w="function"==typeof Object.create?Object.create(null):{},b={},E=t.settings.springTransform||r;f(),s();var L={step:function(){return t.step()},getNodePosition:function(e){return m(e).pos},setNodePosition:function(e){var n=m(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return t.getBBox()},pinNode:function(e,n){var t=m(e.id);t.isPinned=!!n},isNodePinned:function(e){return m(e.id).isPinned},dispose:function(){n.off("changed",u)},getBody:a,getSpring:i,simulator:t};return L}function r(){}n.exports=t,n.exports.simulator=e("ngraph.physics.simulator");var o=e("varta")},{"ngraph.physics.simulator":8,varta:21}],8:[function(e,n){function t(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.force.reset(),v.updateBodyForce(e),m.update(e);for(n=p.length;n--;)g.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),s=n.createBounds||e("./lib/bounds"),u=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),h=s(l,n),g=f(n),m=u(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return h.update(),en))return l.splice(n,1),0===l.length&&h.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return h.getBestNewPosition(e)},getBBox:function(){return h.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=t},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":25,"ngraph.quadtreebh":17}],9:[function(e,n){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var s=n[e];s.isPinned?(s.pos.x=s.prevPos.x,s.pos.y=s.prevPos.y):(s.prevPos.x=s.pos.x,s.prevPos.y=s.pos.y),s.pos.xo&&(o=s.pos.x),s.pos.ya&&(a=s.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var s=0;st;++t){var u=e[t],f=n/u.mass;u.velocity.x+=f*u.force.x,u.velocity.y+=f*u.force.y;var c=u.velocity.x,d=u.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(u.velocity.x=c/l,u.velocity.y=d/l),r=n*u.velocity.x,i=n*u.velocity.y,u.pos.x+=r,u.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=t},{}],13:[function(e,n){function t(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=t},{}],14:[function(e,n){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,s=o.pos.y-t.pos.y,u=Math.sqrt(a*a+s*s);0===u&&(a=(r.nextDouble()-.5)/50,s=(r.nextDouble()-.5)/50,u=Math.sqrt(a*a+s*s));var f=u-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/u*e.weight;t.force.x+=c*a,t.force.y+=c*s,o.force.x-=c*a,o.force.y-=c*s}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":25,"ngraph.random":26}],15:[function(e,n){function t(e,n,t){var o="[object Array]"===Object.prototype.toString.call(t);if(o)for(var i=0;i0&&i(a.pos,o.pos));if(0===s&&i(a.pos,o.pos))return}u.push(r,a),u.push(r,o)}else{var v=o.pos.x,h=o.pos.y;r.mass=r.mass+o.mass,r.massX=r.massX+o.mass*v,r.massY=r.massY+o.mass*h;var g=0,m=r.left,y=(r.right+m)/2,x=r.top,w=(r.bottom+x)/2;if(v>y){g+=1;var b=m;m=y,y+=y-b}if(h>w){g+=2;var E=x;x=w,w+=w-E}var L=r.quads[g];L?u.push(L,o):(L=l(),L.left=m,L.top=x,L.right=y,L.bottom=w,L.body=o,r.quads[g]=L)}}},h=function(e){var n,r,o,i,u=s,c=0,d=0,l=1,v=0,h=1;for(u[0]=p;l;){var g=u[v],m=g.body;l-=1,v+=1,m&&m!==e?(r=m.pos.x-e.pos.x,o=m.pos.y-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),n=a*m.mass*e.mass/(i*i*i),c+=n*r,d+=n*o):(r=g.massX/g.mass-e.pos.x,o=g.massY/g.mass-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),(g.right-g.left)/is&&(t=s),s>o&&(o=s),r>u&&(r=u),u>i&&(i=u)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,d=0,p=l(),p.left=t,p.right=o,p.top=r,p.bottom=i,n=a-1,n>0&&(p.body=e[n]);n--;)v(e[n],p)};return{insertBodies:g,updateBodyForce:h,options:function(e){return e?("number"==typeof e.gravity&&(a=e.gravity),"number"==typeof e.theta&&(f=e.theta),this):{gravity:a,theta:f}}}}},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":26}],18:[function(e,n){function t(){this.stack=[],this.popIdx=0}function r(e,n){this.node=e,this.body=n}n.exports=t,t.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new r(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],19:[function(e,n){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],20:[function(e,n){n.exports=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],21:[function(e,n){function t(e,n){function t(){return o(e,n,arguments)}return n=n||"Argument",{has:t}}function r(){function e(e,t){return o(e,t,n)}var n=arguments;return e}function o(e,n,t){if(void 0===e)throw new Error(n+" is not defined");for(var r=0;re)throw new Error("Invalid number of nodes");var n,t=l();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function r(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=t(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function o(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=l();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function i(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=l();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function a(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=l();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function s(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=l();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function u(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=l();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var s=i*e*n,u=r+o*e+s;r>0&&a.addLink(u,r-1+o*e+s),o>0&&a.addLink(u,r+(o-1)*e+s),i>0&&a.addLink(u,r+o*e+(i-1)*e*n)}return a}function f(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=l(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function c(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=l();for(n=0;e>n;++n)t.addNode(n);return t}function d(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,s=e("ngraph.random").random(o||42),u=l();for(i=0;n>i;++i)u.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,u.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(s.nextDouble()n)return!1;S(),P.splice(n,1);var t=u(e.fromId),o=u(e.toId);return t&&(n=r(e,t.links),n>=0&&t.links.splice(n,1)),o&&(n=r(e,o.links),n>=0&&o.links.splice(n,1)),T(e,"remove"),D(),!0}function p(e,n){var t,r=u(e);if(!r)return null;for(t=0;tn;++n)e(P[n])}function g(e,n,t){var r,o,i,a=u(e);if(a&&a.links&&"function"==typeof n)if(t)for(r=0;r0&&(M.fire("changed",I),I.length=0)}function w(){return Object.keys?b:E}function b(e){if("function"==typeof e)for(var n=Object.keys(L),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function o(e){this.id=e,this.links=[],this.data=null}function i(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=t;var a=e("ngraph.events")},{"ngraph.events":6}],25:[function(e,n){function t(e,n){var r;if(e||(e={}),n)for(r in n)if(n.hasOwnProperty(r)){var o=e.hasOwnProperty(r),i=typeof n[r],a=!o||typeof e[r]!==i;a?e[r]=n[r]:"object"===i&&(e[r]=t(e[r],n[r]))}return e}n.exports=t},{}],26:[function(e,n){function t(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function r(e,n){var r=n||t();if("function"!=typeof r.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var t,o,i;for(t=e.length-1;t>0;--t)o=r.next(t+1),i=e[o],e[o]=e[t],e[t]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,t,o;for(n=e.length-1;n>0;--n)t=r.next(n+1),o=e[t],e[t]=e[n],e[n]=o;return e}}}n.exports={random:t,randomIterator:r}},{}],27:[function(e,n){function t(e,n,t){function r(e){s.nodes.push(u(e))}function o(e){s.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var s={nodes:[],links:[]},u=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(s)}n.exports=t},{}],28:[function(e,n){function t(e,n){var t=r(e);if(void 0===n)return t;for(var o=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),s(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},k=function(e){p=!1,r.off("touchmove",A),r.off("touchend",k),r.off("touchcancel",k),c=null,a&&a(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,r.on("touchmove",A),r.on("touchend",k),r.on("touchcancel",k))},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return a=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),r.off("mousemove",w),r.off("mouseup",E),r.off("touchmove",A),r.off("touchend",k),r.off("touchcancel",k),P(null) +}}}n.exports=t;var r=e("../Utils/documentEvents.js"),o=e("../Utils/browserInfo.js"),i=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":40,"../Utils/documentEvents.js":41,"../Utils/findElementPosition.js":42}],37:[function(e,n){function t(e,n){var t=r(n),o=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){o=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(o);var r=i[e.id];return r&&r.onStart&&r.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(o),o=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(o){var t=i[o.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=t;var r=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":58}],38:[function(e,n){function t(e,n){function t(e){return d[e]}n=r(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var a=o(n.seed),s=new i(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),u={},f=function(){return{x:a.next(n.maxX),y:a.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],s)},p=function(){0!==e.getNodesCount()&&(s.x1=Number.MAX_VALUE,s.y1=Number.MAX_VALUE,s.x2=Number.MIN_VALUE,s.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){u[e.id]=e},h=function(e){for(var n=0;n0)for(e=0;en,t)}),e.forEachNode(O),H(),e.on("changed",q)},K=function(){y=!1,H(),W(),a.off("resize",V),j.removeAllListeners(),l.stop(),e.forEachLink(function(e){n.renderLinks&&B(e)}),e.forEachNode(function(e){F(e),U(e)}),v.dispose(),z()};return{run:function(e){return y||(k(),S(),D(),G(),$(),y=!0),T(e),this},reset:function(){h.resetScale(),D(),A.scale=1},pause:function(){P=!0,l.stop()},resume:function(){P=!1,l.restart()},rerender:function(){return _(),this},zoomOut:function(){return J(!0)},zoomIn:function(){return J(!1)},moveTo:function(e,n){h.graphCenterChanged(A.offsetX-e*A.scale,A.offsetY-n*A.scale),_()},getGraphics:function(){return h},dispose:function(){K()},on:function(e,n){return j.addEventListener(e,n),this},off:function(e,n){return j.removeEventListener(e,n),this}}}n.exports=t;var r=e("ngraph.graph"),o=e("ngraph.forcelayout"),i=e("./svgGraphics.js"),a=e("../Utils/windowEvents.js"),s=e("../Input/domInputManager.js"),u=e("../Utils/timer.js"),f=e("../Utils/getDimensions.js"),c=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.forcelayout":7,"ngraph.graph":24}],50:[function(e,n){function t(){function e(){var e=r("svg");return n=r("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,a,s,u,f=1,c={},d={},l=function(){return r("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(){return r("line").attr("stroke","#999")},h=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},g=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+a+","+s+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return h=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){a=e,s=n,w()},inputManager:i,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var s="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",s)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),u=n.getCTM().multiply(i);f=u.a,a=u.e,s=u.f;var c="matrix("+u.a+", 0, 0,"+u.d+","+u.e+","+u.f+")";return n.attr("transform",c),g(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),g(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof u&&u(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,h(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):u=e),t},getSvgRoot:function(){return t}};return o(b),b}n.exports=t;var r=e("simplesvg"),o=e("ngraph.events"),i=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":35,"ngraph.events":6,simplesvg:28}],51:[function(e,n){function t(e){e=f(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,c,d,l,p,v,h,g=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=o(),P=i(),N=function(){return a()},A=function(){return s(3014898687)},k=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),c&&c.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(A=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:r,beginRender:function(){},endRender:function(){m>0&&L.render(),g>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,k()},addLink:function(e,n){var t=m++,r=A(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=g++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],k()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,k(),I(this),y[0]},resetScale:function(){return j(),c&&(_(),k()),this},init:function(r){var o={};if(e.preserveDrawingBuffer&&(o.preserveDrawingBuffer=!0),n=r,_(),j(),n.appendChild(t),c=t.getContext("experimental-webgl",o),!c){var i="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(i),i}if(e.enableBlending&&(c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA),c.enable(c.BLEND)),e.clearColor){var a=e.clearColorValue;c.clearColor(a.r,a.g,a.b,a.a),this.beginRender=function(){c.clear(c.COLOR_BUFFER_BIT)}}L.load(c),L.updateSize(d/2,l/2),P.load(c),P.updateSize(d/2,l/2),k(),"function"==typeof h&&h(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){g>0&&(g-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(g>t){if(0===g||g===t)return;var r=x[g];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;g>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):h=e),t},setNodeProgram:function(e){if(!c&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!c&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;g>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return u(T),T}n.exports=t;var r=e("../Input/webglInputManager.js"),o=e("../WebGL/webglLinkProgram.js"),i=e("../WebGL/webglNodeProgram.js"),a=e("../WebGL/webglSquare.js"),s=e("../WebGL/webglLine.js"),u=e("ngraph.events"),f=e("ngraph.merge")},{"../Input/webglInputManager.js":37,"../WebGL/webglLine.js":59,"../WebGL/webglLinkProgram.js":60,"../WebGL/webglNodeProgram.js":61,"../WebGL/webglSquare.js":62,"ngraph.events":6,"ngraph.merge":25}],52:[function(e,n){function t(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=t},{}],53:[function(e,n){function t(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=t},{}],54:[function(e,n){function t(e){var n=function(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r};return{createProgram:function(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var s=e.getShaderInfoLog(o);throw window.alert(s),s}return o},extendArray:function(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e},copyArrayPart:function(e,n,t,r){var o;for(o=0;r>o;++o)e[n+o]=e[t+o]},swapArrayPart:function(e,n,t,r){var o;for(o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}},getLocations:function(n,t){var r,o={};for(r=0;r10?v():n=window.setTimeout(v,400)},g=function(e,n){var t=f[e.textureNumber].canvas,r=f[n.textureNumber].ctx,o=n.col*i,a=n.row*i;r.drawImage(t,e.col*i,e.row*i,i,i,o,a,i,i),f[e.textureNumber].isDirty=!0,f[n.textureNumber].isDirty=!0},m=function(e,n,t){var r=p(e),o={offset:e};r.textureNumber>=f.length&&l();var a=f[r.textureNumber];a.ctx.drawImage(n,r.col*i,r.row*i,i,i),c[e]=n.src,s[n.src]=o,a.isDirty=!0,t(o)};if(!d(e))throw"Tiles per texture should be power of two.";return t={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;e0&&(g-=1),n.id0&&(n.src&&e.remove(n.src),a.copyArrayPart(m,n.id*l,g*l,l))},replaceProperties:function(e,n){n._offset=e._offset},updateTransform:function(e){d=!0,c=e},updateSize:function(e,n){u=e,f=n,d=!0},render:function(){t.useProgram(n),t.bindBuffer(t.ARRAY_BUFFER,i),t.bufferData(t.ARRAY_BUFFER,m,t.DYNAMIC_DRAW),d&&(d=!1,t.uniformMatrix4fv(s.transform,!1,c),t.uniform2f(s.screenSize,u,f)),t.vertexAttribPointer(s.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(s.customAttributes,1,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),x(),t.drawArrays(t.TRIANGLES,0,6*g)}}}var r=e("./webglAtlas.js"),o=e("./webgl.js");n.exports=t},{"./webgl.js":54,"./webglAtlas.js":55}],58:[function(e,n){function t(e){if(e.webglInputEvents)return e.webglInputEvents;var n,t,o=function(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oa-x&&r[0]===m?g(p,r):g(l,r),x=a,g(c,r)&&v(e))})};return e.getGraphicsRoot(m),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&s.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&f.push(e),this},mouseUp:function(e){return"function"==typeof e&&c.push(e),this},mouseMove:function(e){return"function"==typeof e&&d.push(e),this},click:function(e){return"function"==typeof e&&l.push(e),this},dblClick:function(e){return"function"==typeof e&&p.push(e),this},mouseCapture:function(e){a=e},releaseMouseCapture:function(){a=null}},e.webglInputEvents}var r=e("../Utils/documentEvents.js");n.exports=t},{"../Utils/documentEvents.js":41}],59:[function(e,n){function t(e){return{color:r(e)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],60:[function(e,n){function t(){var e,n,t,o,i,a,s,u,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),h=0,g=new ArrayBuffer(16*l),m=new Float32Array(g),y=new Uint32Array(g),x=function(){if((h+1)*l>g.byteLength){var e=new ArrayBuffer(2*g.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,g=e}};return{load:function(a){n=a,o=r(a),e=o.createProgram(v,p),n.useProgram(e),i=o.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),h+=1,a=e.id},removeLink:function(e){h>0&&(h-=1),e.id0&&o.copyArrayPart(y,e.id*d,h*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){s=e,u=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,g,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,s,u)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*h),a=h-1},bringToFront:function(e){a>e.id&&o.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],61:[function(e,n){function t(){var e,n,t,o,i,a,s,u,f,c=4,d=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),p=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),v=new ArrayBuffer(16*d),h=new Float32Array(v),g=new Uint32Array(v),m=0,y=function(){if((m+1)*d>=v.byteLength){var e=new ArrayBuffer(2*v.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(g),h=n,g=t,v=e}};return{load:function(a){n=a,i=r(a),e=i.createProgram(p,l),n.useProgram(e),o=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.color),t=n.createBuffer()},position:function(e,n){var t=e.id;h[t*c]=n.x,h[t*c+1]=n.y,h[t*c+2]=e.size,g[t*c+3]=e.color},updateTransform:function(e){f=!0,u=e},updateSize:function(e,n){a=e,s=n,f=!0},removeNode:function(e){m>0&&(m-=1),e.id0&&i.copyArrayPart(g,e.id*c,m*c,c)},createNode:function(){y(),m+=1},replaceProperties:function(){},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,v,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,u),n.uniform2f(o.screenSize,a,s)),n.vertexAttribPointer(o.vertexPos,3,n.FLOAT,!1,c*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.color,4,n.UNSIGNED_BYTE,!0,c*Float32Array.BYTES_PER_ELEMENT,12),n.drawArrays(n.POINTS,0,m)}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],62:[function(e,n){function t(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],63:[function(e,n){n.exports="0.7.2"},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/package.json b/package.json index 1ce4847..1ced9b8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.7.0", + "version": "0.7.1", "description": "Graph Drawing Library", "main": "dist/vivagraph", "directories": { @@ -36,9 +36,9 @@ "ngraph.centrality": "0.1.1", "ngraph.events": "0.0.3", "ngraph.forcelayout": "0.0.15", - "ngraph.fromjson": "0.1.3", - "ngraph.generators": "0.0.12", - "ngraph.graph": "0.0.7", + "ngraph.fromjson": "0.1.4", + "ngraph.generators": "0.0.13", + "ngraph.graph": "0.0.8", "ngraph.merge": "0.0.1", "ngraph.random": "0.0.1", "ngraph.tojson": "0.1.1", diff --git a/src/version.js b/src/version.js index 4ca8809..a85f616 100644 --- a/src/version.js +++ b/src/version.js @@ -1 +1 @@ -module.exports = '0.7.0'; +module.exports = '0.7.2'; From 8dd01d3a96f3eae08300921273b6995c1679c1ec Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 7 Feb 2015 12:56:56 -0800 Subject: [PATCH 160/276] 0.7.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1ced9b8..bb75a39 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.7.1", + "version": "0.7.2", "description": "Graph Drawing Library", "main": "dist/vivagraph", "directories": { From 86c2b5cff5d779eea6b3f796af9dc5acedf86eb2 Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 11 Feb 2015 17:15:41 -0800 Subject: [PATCH 161/276] do away with anonymous functions --- src/WebGL/webgl.js | 187 +++++++++++++++++++++++---------------------- 1 file changed, 95 insertions(+), 92 deletions(-) diff --git a/src/WebGL/webgl.js b/src/WebGL/webgl.js index 6fadbaa..94b8773 100644 --- a/src/WebGL/webgl.js +++ b/src/WebGL/webgl.js @@ -7,96 +7,99 @@ module.exports = webgl; function webgl(gl) { - var createShader = function (shaderText, type) { - var shader = gl.createShader(type); - gl.shaderSource(shader, shaderText); - gl.compileShader(shader); - - if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { - var msg = gl.getShaderInfoLog(shader); - window.alert(msg); - throw msg; - } - - return shader; - }; - - return { - createProgram : function (vertexShaderSrc, fragmentShaderSrc) { - var program = gl.createProgram(), - vs = createShader(vertexShaderSrc, gl.VERTEX_SHADER), - fs = createShader(fragmentShaderSrc, gl.FRAGMENT_SHADER); - - gl.attachShader(program, vs); - gl.attachShader(program, fs); - gl.linkProgram(program); - - if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { - var msg = gl.getShaderInfoLog(program); - window.alert(msg); - throw msg; - } - - return program; - }, - - extendArray : function (buffer, itemsInBuffer, elementsPerItem) { - if ((itemsInBuffer + 1) * elementsPerItem > buffer.length) { - // Every time we run out of space create new array twice bigger. - // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs - var extendedArray = new Float32Array(buffer.length * elementsPerItem * 2); - extendedArray.set(buffer); - - return extendedArray; - } - - return buffer; - }, - - copyArrayPart : function (array, to, from, elementsCount) { - var i; - for (i = 0; i < elementsCount; ++i) { - array[to + i] = array[from + i]; - } - }, - - swapArrayPart : function (array, from, to, elementsCount) { - var i; - for (i = 0; i < elementsCount; ++i) { - var tmp = array[from + i]; - array[from + i] = array[to + i]; - array[to + i] = tmp; - } - }, - - getLocations : function (program, uniformOrAttributeNames) { - var foundLocations = {}, - i; - for (i = 0; i < uniformOrAttributeNames.length; ++i) { - var name = uniformOrAttributeNames[i], - location = -1; - if (name.indexOf("a_") === 0) { - location = gl.getAttribLocation(program, name); - if (location === -1) { - throw "Program doesn't have required attribute: " + name; - } - - foundLocations[name.slice(2)] = location; - } else if (name.indexOf("u_") === 0) { - location = gl.getUniformLocation(program, name); - if (location === null) { - throw "Program doesn't have required uniform: " + name; - } - - foundLocations[name.slice(2)] = location; - } else { - throw "Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'"; - } - } - - return foundLocations; - }, - - context : gl - }; + + return { + createProgram: createProgram, + extendArray: extendArray, + copyArrayPart: copyArrayPart, + swapArrayPart: swapArrayPart, + getLocations: getLocations, + context: gl + }; + + function createShader(shaderText, type) { + var shader = gl.createShader(type); + gl.shaderSource(shader, shaderText); + gl.compileShader(shader); + + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + var msg = gl.getShaderInfoLog(shader); + window.alert(msg); + throw msg; + } + + return shader; + } + + function createProgram(vertexShaderSrc, fragmentShaderSrc) { + var program = gl.createProgram(); + var vs = createShader(vertexShaderSrc, gl.VERTEX_SHADER); + var fs = createShader(fragmentShaderSrc, gl.FRAGMENT_SHADER); + + gl.attachShader(program, vs); + gl.attachShader(program, fs); + gl.linkProgram(program); + + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { + var msg = gl.getShaderInfoLog(program); + window.alert(msg); + throw msg; + } + + return program; + } + + function extendArray(buffer, itemsInBuffer, elementsPerItem) { + if ((itemsInBuffer + 1) * elementsPerItem > buffer.length) { + // Every time we run out of space create new array twice bigger. + // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs + var extendedArray = new Float32Array(buffer.length * elementsPerItem * 2); + extendedArray.set(buffer); + + return extendedArray; + } + + return buffer; + } + + function getLocations(program, uniformOrAttributeNames) { + var foundLocations = {}; + for (var i = 0; i < uniformOrAttributeNames.length; ++i) { + var name = uniformOrAttributeNames[i]; + var location = -1; + if (name[0] === 'a' && name[1] === '_') { + location = gl.getAttribLocation(program, name); + if (location === -1) { + throw new Error("Program doesn't have required attribute: " + name); + } + + foundLocations[name.slice(2)] = location; + } else if (name[0] === 'u' && name[1] === '_') { + location = gl.getUniformLocation(program, name); + if (location === null) { + throw new Error("Program doesn't have required uniform: " + name); + } + + foundLocations[name.slice(2)] = location; + } else { + throw new Error("Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'"); + } + } + + return foundLocations; + } +} + +function copyArrayPart(array, to, from, elementsCount) { + for (var i = 0; i < elementsCount; ++i) { + array[to + i] = array[from + i]; + } +} + +function swapArrayPart(array, from, to, elementsCount) { + for (var i = 0; i < elementsCount; ++i) { + var tmp = array[from + i]; + array[from + i] = array[to + i]; + array[to + i] = tmp; + } } From 52b39b351ec60cc4f52d2b58b8f518bd6ec88c55 Mon Sep 17 00:00:00 2001 From: anvaka Date: Thu, 12 Feb 2015 19:12:09 -0800 Subject: [PATCH 162/276] Removed anonymouse functions --- src/WebGL/webglNodeProgram.js | 277 ++++++++++++++++++---------------- 1 file changed, 147 insertions(+), 130 deletions(-) diff --git a/src/WebGL/webglNodeProgram.js b/src/WebGL/webglNodeProgram.js index 8b1d66b..70e2d2d 100644 --- a/src/WebGL/webglNodeProgram.js +++ b/src/WebGL/webglNodeProgram.js @@ -13,134 +13,151 @@ module.exports = webglNodeProgram; * Defines simple UI for nodes in webgl renderer. Each node is rendered as square. Color and size can be changed. */ function webglNodeProgram() { - var ATTRIBUTES_PER_PRIMITIVE = 4, // Primitive is point, x, y, size, color - // x, y, z - floats, color = uint. - BYTES_PER_NODE = 3 * Float32Array.BYTES_PER_ELEMENT + Uint32Array.BYTES_PER_ELEMENT, - nodesFS = [ - 'precision mediump float;', - 'varying vec4 color;', - - 'void main(void) {', - ' gl_FragColor = color;', - '}' - ].join('\n'), - nodesVS = [ - 'attribute vec3 a_vertexPos;', - 'attribute vec4 a_color;', - 'uniform vec2 u_screenSize;', - 'uniform mat4 u_transform;', - 'varying vec4 color;', - - 'void main(void) {', - ' gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);', - ' gl_PointSize = a_vertexPos.z * u_transform[0][0];', - ' color = a_color.abgr;', - '}' - ].join('\n'), - - program, - gl, - buffer, - locations, - utils, - storage = new ArrayBuffer(16 * BYTES_PER_NODE), - positions = new Float32Array(storage), - colors = new Uint32Array(storage), - nodesCount = 0, - width, - height, - transform, - sizeDirty, - - ensureEnoughStorage = function () { - if ((nodesCount + 1) * BYTES_PER_NODE >= storage.byteLength) { - // Every time we run out of space create new array twice bigger. - // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs - var extendedStorage = new ArrayBuffer(storage.byteLength * 2), - extendedPositions = new Float32Array(extendedStorage), - extendedColors = new Uint32Array(extendedStorage); - - extendedColors.set(colors); // should be enough to copy just one view. - positions = extendedPositions; - colors = extendedColors; - storage = extendedStorage; - } - }; - - return { - load : function (glContext) { - gl = glContext; - utils = glUtils(glContext); - - program = utils.createProgram(nodesVS, nodesFS); - gl.useProgram(program); - locations = utils.getLocations(program, ['a_vertexPos', 'a_color', 'u_screenSize', 'u_transform']); - - gl.enableVertexAttribArray(locations.vertexPos); - gl.enableVertexAttribArray(locations.color); - - buffer = gl.createBuffer(); - }, - - /** - * Updates position of node in the buffer of nodes. - * - * @param idx - index of current node. - * @param pos - new position of the node. - */ - position : function (nodeUI, pos) { - var idx = nodeUI.id; - - positions[idx * ATTRIBUTES_PER_PRIMITIVE] = pos.x; - positions[idx * ATTRIBUTES_PER_PRIMITIVE + 1] = pos.y; - positions[idx * ATTRIBUTES_PER_PRIMITIVE + 2] = nodeUI.size; - - colors[idx * ATTRIBUTES_PER_PRIMITIVE + 3] = nodeUI.color; - }, - - updateTransform : function (newTransform) { - sizeDirty = true; - transform = newTransform; - }, - - updateSize : function (w, h) { - width = w; - height = h; - sizeDirty = true; - }, - - removeNode : function (node) { - if (nodesCount > 0) { nodesCount -= 1; } - - if (node.id < nodesCount && nodesCount > 0) { - // we can use colors as a 'view' into array array buffer. - utils.copyArrayPart(colors, node.id * ATTRIBUTES_PER_PRIMITIVE, nodesCount * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); - } - }, -/*jshint unused:false */ - createNode : function (node) { - ensureEnoughStorage(); - nodesCount += 1; - }, - - replaceProperties : function (replacedNode, newNode) {}, -/*jshint unused:true */ - - render : function () { - gl.useProgram(program); - gl.bindBuffer(gl.ARRAY_BUFFER, buffer); - gl.bufferData(gl.ARRAY_BUFFER, storage, gl.DYNAMIC_DRAW); - - if (sizeDirty) { - sizeDirty = false; - gl.uniformMatrix4fv(locations.transform, false, transform); - gl.uniform2f(locations.screenSize, width, height); - } - - gl.vertexAttribPointer(locations.vertexPos, 3, gl.FLOAT, false, ATTRIBUTES_PER_PRIMITIVE * Float32Array.BYTES_PER_ELEMENT, 0); - gl.vertexAttribPointer(locations.color, 4, gl.UNSIGNED_BYTE, true, ATTRIBUTES_PER_PRIMITIVE * Float32Array.BYTES_PER_ELEMENT, 3 * 4); - - gl.drawArrays(gl.POINTS, 0, nodesCount); - } - }; + var ATTRIBUTES_PER_PRIMITIVE = 4; // Primitive is point, x, y, size, color + // x, y, z - floats, color = uint. + var BYTES_PER_NODE = 3 * Float32Array.BYTES_PER_ELEMENT + Uint32Array.BYTES_PER_ELEMENT; + var nodesFS = [ + 'precision mediump float;', + 'varying vec4 color;', + + 'void main(void) {', + ' gl_FragColor = color;', + '}' + ].join('\n'); + var nodesVS = [ + 'attribute vec3 a_vertexPos;', + 'attribute vec4 a_color;', + 'uniform vec2 u_screenSize;', + 'uniform mat4 u_transform;', + 'varying vec4 color;', + + 'void main(void) {', + ' gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);', + ' gl_PointSize = a_vertexPos.z * u_transform[0][0];', + ' color = a_color.abgr;', + '}' + ].join('\n'); + + var program; + var gl; + var buffer; + var locations; + var utils; + var storage = new ArrayBuffer(16 * BYTES_PER_NODE); + var positions = new Float32Array(storage); + var colors = new Uint32Array(storage); + var nodesCount = 0; + var width; + var height; + var transform; + var sizeDirty; + + return { + load: load, + + /** + * Updates position of node in the buffer of nodes. + * + * @param idx - index of current node. + * @param pos - new position of the node. + */ + position: position, + + updateTransform: updateTransform, + + updateSize: updateSize, + + removeNode: removeNode, + + createNode: createNode, + + replaceProperties: replaceProperties, + + render: render + }; + + function ensureEnoughStorage() { + if ((nodesCount + 1) * BYTES_PER_NODE >= storage.byteLength) { + // Every time we run out of space create new array twice bigger. + // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs + var extendedStorage = new ArrayBuffer(storage.byteLength * 2), + extendedPositions = new Float32Array(extendedStorage), + extendedColors = new Uint32Array(extendedStorage); + + extendedColors.set(colors); // should be enough to copy just one view. + positions = extendedPositions; + colors = extendedColors; + storage = extendedStorage; + } + } + + function load(glContext) { + gl = glContext; + utils = glUtils(glContext); + + program = utils.createProgram(nodesVS, nodesFS); + gl.useProgram(program); + locations = utils.getLocations(program, ['a_vertexPos', 'a_color', 'u_screenSize', 'u_transform']); + + gl.enableVertexAttribArray(locations.vertexPos); + gl.enableVertexAttribArray(locations.color); + + buffer = gl.createBuffer(); + } + + function position(nodeUI, pos) { + var idx = nodeUI.id; + + positions[idx * ATTRIBUTES_PER_PRIMITIVE] = pos.x; + positions[idx * ATTRIBUTES_PER_PRIMITIVE + 1] = pos.y; + positions[idx * ATTRIBUTES_PER_PRIMITIVE + 2] = nodeUI.size; + + colors[idx * ATTRIBUTES_PER_PRIMITIVE + 3] = nodeUI.color; + } + + function updateTransform(newTransform) { + sizeDirty = true; + transform = newTransform; + } + + function updateSize(w, h) { + width = w; + height = h; + sizeDirty = true; + } + + function removeNode(node) { + if (nodesCount > 0) { + nodesCount -= 1; + } + + if (node.id < nodesCount && nodesCount > 0) { + // we can use colors as a 'view' into array array buffer. + utils.copyArrayPart(colors, node.id * ATTRIBUTES_PER_PRIMITIVE, nodesCount * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); + } + } + + function createNode() { + ensureEnoughStorage(); + nodesCount += 1; + } + + function replaceProperties(/* replacedNode, newNode */) {} + + function render() { + gl.useProgram(program); + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData(gl.ARRAY_BUFFER, storage, gl.DYNAMIC_DRAW); + + if (sizeDirty) { + sizeDirty = false; + gl.uniformMatrix4fv(locations.transform, false, transform); + gl.uniform2f(locations.screenSize, width, height); + } + + gl.vertexAttribPointer(locations.vertexPos, 3, gl.FLOAT, false, ATTRIBUTES_PER_PRIMITIVE * Float32Array.BYTES_PER_ELEMENT, 0); + gl.vertexAttribPointer(locations.color, 4, gl.UNSIGNED_BYTE, true, ATTRIBUTES_PER_PRIMITIVE * Float32Array.BYTES_PER_ELEMENT, 3 * 4); + + gl.drawArrays(gl.POINTS, 0, nodesCount); + } } From d317589d0df5bf0eea997db8542b6cff86b85d53 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 14 Feb 2015 12:54:44 -0800 Subject: [PATCH 163/276] More grooming - less anonymous functions --- src/Utils/timer.js | 145 ++++++++++++++++++++++++--------------------- 1 file changed, 78 insertions(+), 67 deletions(-) diff --git a/src/Utils/timer.js b/src/Utils/timer.js index 9233a83..8e79c42 100644 --- a/src/Utils/timer.js +++ b/src/Utils/timer.js @@ -5,77 +5,88 @@ module.exports = createTimer(); function createTimer() { - var lastTime = 0, - vendors = ['ms', 'moz', 'webkit', 'o'], - i, - scope; - - if (typeof window !== 'undefined') { - scope = window; - } else if (typeof global !== 'undefined') { - scope = global; - } else { - scope = { - setTimeout: function () {}, - clearTimeout: function () {} - }; - } - for (i = 0; i < vendors.length && !scope.requestAnimationFrame; ++i) { - var vendorPrefix = vendors[i]; - scope.requestAnimationFrame = scope[vendorPrefix + 'RequestAnimationFrame']; - scope.cancelAnimationFrame = - scope[vendorPrefix + 'CancelAnimationFrame'] || scope[vendorPrefix + 'CancelRequestAnimationFrame']; - } + var lastTime = 0, + vendors = ['ms', 'moz', 'webkit', 'o'], + i, + scope; + + if (typeof window !== 'undefined') { + scope = window; + } else if (typeof global !== 'undefined') { + scope = global; + } else { + scope = { + setTimeout: noop, + clearTimeout: noop + }; + } + + for (i = 0; i < vendors.length && !scope.requestAnimationFrame; ++i) { + var vendorPrefix = vendors[i]; + scope.requestAnimationFrame = scope[vendorPrefix + 'RequestAnimationFrame']; + scope.cancelAnimationFrame = + scope[vendorPrefix + 'CancelAnimationFrame'] || scope[vendorPrefix + 'CancelRequestAnimationFrame']; + } + + if (!scope.requestAnimationFrame) { + scope.requestAnimationFrame = rafPolyfill; + } + + if (!scope.cancelAnimationFrame) { + scope.cancelAnimationFrame = cancelRafPolyfill; + } + + return timer; - if (!scope.requestAnimationFrame) { - scope.requestAnimationFrame = function (callback) { - var currTime = new Date().getTime(); - var timeToCall = Math.max(0, 16 - (currTime - lastTime)); - var id = scope.setTimeout(function () { callback(currTime + timeToCall); }, timeToCall); - lastTime = currTime + timeToCall; - return id; - }; + /** + * Timer that fires callback with given interval (in ms) until + * callback returns true; + */ + function timer(callback) { + var intervalId; + startTimer(); // start it right away. + + return { + /** + * Stops execution of the callback + */ + stop: stopTimer, + + restart: restart + }; + + function startTimer() { + intervalId = scope.requestAnimationFrame(startTimer); + if (!callback()) { + stopTimer(); + } } - if (!scope.cancelAnimationFrame) { - scope.cancelAnimationFrame = function (id) { - scope.clearTimeout(id); - }; + function stopTimer() { + scope.cancelAnimationFrame(intervalId); + intervalId = 0; } - return timer; - - /** - * Timer that fires callback with given interval (in ms) until - * callback returns true; - */ - function timer(callback) { - var intervalId, - stopTimer = function () { - scope.cancelAnimationFrame(intervalId); - intervalId = 0; - }, - - startTimer = function () { - intervalId = scope.requestAnimationFrame(startTimer); - if (!callback()) { - stopTimer(); - } - }; - - startTimer(); // start it right away. - - return { - /** - * Stops execution of the callback - */ - stop: stopTimer, - - restart : function () { - if (!intervalId) { - startTimer(); - } - } - }; + function restart() { + if (!intervalId) { + startTimer(); + } } + } + + function rafPolyfill(callback) { + var currTime = new Date().getTime(); + var timeToCall = Math.max(0, 16 - (currTime - lastTime)); + var id = scope.setTimeout(function() { + callback(currTime + timeToCall); + }, timeToCall); + lastTime = currTime + timeToCall; + return id; + } + + function cancelRafPolyfill(id) { + scope.clearTimeout(id); + } } + +function noop() {} From bd43825cd3685ef7b058b97e6df85d892e5962ef Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 15 Feb 2015 08:03:18 -0800 Subject: [PATCH 164/276] Removed anonymous functions --- src/WebGL/webglImageNodeProgram.js | 463 +++++++++++++++-------------- 1 file changed, 244 insertions(+), 219 deletions(-) diff --git a/src/WebGL/webglImageNodeProgram.js b/src/WebGL/webglImageNodeProgram.js index 0169ead..fc52020 100644 --- a/src/WebGL/webglImageNodeProgram.js +++ b/src/WebGL/webglImageNodeProgram.js @@ -14,224 +14,249 @@ module.exports = webglImageNodeProgram; * Defines simple UI for nodes in webgl renderer. Each node is rendered as an image. */ function webglImageNodeProgram() { - var ATTRIBUTES_PER_PRIMITIVE = 18, - // TODO: Use glslify for shaders - nodesFS = [ - "precision mediump float;", - "varying vec4 color;", - "varying vec3 vTextureCoord;", - "uniform sampler2D u_sampler0;", - "uniform sampler2D u_sampler1;", - "uniform sampler2D u_sampler2;", - "uniform sampler2D u_sampler3;", - - "void main(void) {", - " if (vTextureCoord.z == 0.) {", - " gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);", - " } else if (vTextureCoord.z == 1.) {", - " gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);", - " } else if (vTextureCoord.z == 2.) {", - " gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);", - " } else if (vTextureCoord.z == 3.) {", - " gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);", - " } else { gl_FragColor = vec4(0, 1, 0, 1); }", - "}" - ].join("\n"), - - nodesVS = [ - "attribute vec2 a_vertexPos;", - - "attribute float a_customAttributes;", - "uniform vec2 u_screenSize;", - "uniform mat4 u_transform;", - "uniform float u_tilesPerTexture;", - "varying vec3 vTextureCoord;", - - "void main(void) {", - " gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);", - "float corner = mod(a_customAttributes, 4.);", - "float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);", - "float tilesPerRow = sqrt(u_tilesPerTexture);", - "float tileSize = 1./tilesPerRow;", - "float tileColumn = mod(tileIndex, tilesPerRow);", - "float tileRow = floor(tileIndex/tilesPerRow);", - - "if(corner == 0.0) {", - " vTextureCoord.xy = vec2(0, 1);", - "} else if(corner == 1.0) {", - " vTextureCoord.xy = vec2(1, 1);", - "} else if(corner == 2.0) {", - " vTextureCoord.xy = vec2(0, 0);", - "} else {", - " vTextureCoord.xy = vec2(1, 0);", - "}", - - "vTextureCoord *= tileSize;", - "vTextureCoord.x += tileColumn * tileSize;", - "vTextureCoord.y += tileRow * tileSize;", - "vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);", - "}" - ].join("\n"), - - tilesPerTexture = 1024, // TODO: Get based on max texture size - atlas; - - var program, - gl, - buffer, - utils, - locations, - nodesCount = 0, - nodes = new Float32Array(64), - width, - height, - transform, - sizeDirty, - - refreshTexture = function (texture, idx) { - if (texture.nativeObject) { - gl.deleteTexture(texture.nativeObject); - } - - var nativeObject = gl.createTexture(); - gl.activeTexture(gl["TEXTURE" + idx]); - gl.bindTexture(gl.TEXTURE_2D, nativeObject); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.canvas); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST); - - gl.generateMipmap(gl.TEXTURE_2D); - gl.uniform1i(locations["sampler" + idx], idx); - - texture.nativeObject = nativeObject; - }, - - ensureAtlasTextureUpdated = function () { - if (atlas.isDirty) { - var textures = atlas.getTextures(), - i; - for (i = 0; i < textures.length; ++i) { - if (textures[i].isDirty || !textures[i].nativeObject) { - refreshTexture(textures[i], i); - } - } - - atlas.clearDirty(); - } - }; - - return { - load : function (glContext) { - gl = glContext; - utils = glUtils(glContext); - - atlas = new WebglAtlas(tilesPerTexture); - - program = utils.createProgram(nodesVS, nodesFS); - gl.useProgram(program); - locations = utils.getLocations(program, ["a_vertexPos", "a_customAttributes", "u_screenSize", "u_transform", "u_sampler0", "u_sampler1", "u_sampler2", "u_sampler3", "u_tilesPerTexture"]); - - gl.uniform1f(locations.tilesPerTexture, tilesPerTexture); - - gl.enableVertexAttribArray(locations.vertexPos); - gl.enableVertexAttribArray(locations.customAttributes); - - buffer = gl.createBuffer(); - }, - - /** - * Updates position of current node in the buffer of nodes. - * - * @param idx - index of current node. - * @param pos - new position of the node. - */ - position : function (nodeUI, pos) { - var idx = nodeUI.id * ATTRIBUTES_PER_PRIMITIVE; - nodes[idx] = pos.x - nodeUI.size; - nodes[idx + 1] = pos.y - nodeUI.size; - nodes[idx + 2] = nodeUI._offset * 4; - - nodes[idx + 3] = pos.x + nodeUI.size; - nodes[idx + 4] = pos.y - nodeUI.size; - nodes[idx + 5] = nodeUI._offset * 4 + 1; - - nodes[idx + 6] = pos.x - nodeUI.size; - nodes[idx + 7] = pos.y + nodeUI.size; - nodes[idx + 8] = nodeUI._offset * 4 + 2; - - nodes[idx + 9] = pos.x - nodeUI.size; - nodes[idx + 10] = pos.y + nodeUI.size; - nodes[idx + 11] = nodeUI._offset * 4 + 2; - - nodes[idx + 12] = pos.x + nodeUI.size; - nodes[idx + 13] = pos.y - nodeUI.size; - nodes[idx + 14] = nodeUI._offset * 4 + 1; - - nodes[idx + 15] = pos.x + nodeUI.size; - nodes[idx + 16] = pos.y + nodeUI.size; - nodes[idx + 17] = nodeUI._offset * 4 + 3; - }, - - createNode : function (ui) { - nodes = utils.extendArray(nodes, nodesCount, ATTRIBUTES_PER_PRIMITIVE); - nodesCount += 1; - - var coordinates = atlas.getCoordinates(ui.src); - if (coordinates) { - ui._offset = coordinates.offset; - } else { - ui._offset = 0; - // Image is not yet loaded into the atlas. Reload it: - atlas.load(ui.src, function (coordinates) { - ui._offset = coordinates.offset; - }); - } - }, - - removeNode : function (nodeUI) { - if (nodesCount > 0) { nodesCount -= 1; } - - if (nodeUI.id < nodesCount && nodesCount > 0) { - if (nodeUI.src) { - atlas.remove(nodeUI.src); - } - - utils.copyArrayPart(nodes, nodeUI.id * ATTRIBUTES_PER_PRIMITIVE, nodesCount * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); - } - }, - - replaceProperties : function (replacedNode, newNode) { - newNode._offset = replacedNode._offset; - }, - - updateTransform : function (newTransform) { - sizeDirty = true; - transform = newTransform; - }, - - updateSize : function (w, h) { - width = w; - height = h; - sizeDirty = true; - }, - - render : function () { - gl.useProgram(program); - gl.bindBuffer(gl.ARRAY_BUFFER, buffer); - gl.bufferData(gl.ARRAY_BUFFER, nodes, gl.DYNAMIC_DRAW); - - if (sizeDirty) { - sizeDirty = false; - gl.uniformMatrix4fv(locations.transform, false, transform); - gl.uniform2f(locations.screenSize, width, height); - } - - gl.vertexAttribPointer(locations.vertexPos, 2, gl.FLOAT, false, 3 * Float32Array.BYTES_PER_ELEMENT, 0); - gl.vertexAttribPointer(locations.customAttributes, 1, gl.FLOAT, false, 3 * Float32Array.BYTES_PER_ELEMENT, 2 * 4); - - ensureAtlasTextureUpdated(); - - gl.drawArrays(gl.TRIANGLES, 0, nodesCount * 6); + // WebGL is gian state machine, we store some properties of the state here: + var ATTRIBUTES_PER_PRIMITIVE = 18; + var nodesFS = createNodeFragmentShader(); + var nodesVS = createNodeVertexShader(); + var tilesPerTexture = 1024; // TODO: Get based on max texture size + var atlas; + var program; + var gl; + var buffer; + var utils; + var locations; + var nodesCount = 0; + var nodes = new Float32Array(64); + var width; + var height; + var transform; + var sizeDirty; + + + return { + load: load, + + /** + * Updates position of current node in the buffer of nodes. + * + * @param idx - index of current node. + * @param pos - new position of the node. + */ + position: position, + + createNode: createNode, + + removeNode: removeNode, + + replaceProperties: replaceProperties, + + updateTransform: updateTransform, + + updateSize: updateSize, + + render: render + }; + + function refreshTexture(texture, idx) { + if (texture.nativeObject) { + gl.deleteTexture(texture.nativeObject); + } + + var nativeObject = gl.createTexture(); + gl.activeTexture(gl["TEXTURE" + idx]); + gl.bindTexture(gl.TEXTURE_2D, nativeObject); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.canvas); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST); + + gl.generateMipmap(gl.TEXTURE_2D); + gl.uniform1i(locations["sampler" + idx], idx); + + texture.nativeObject = nativeObject; + } + + function ensureAtlasTextureUpdated() { + if (atlas.isDirty) { + var textures = atlas.getTextures(), + i; + for (i = 0; i < textures.length; ++i) { + if (textures[i].isDirty || !textures[i].nativeObject) { + refreshTexture(textures[i], i); } - }; + } + + atlas.clearDirty(); + } + } + + function load(glContext) { + gl = glContext; + utils = glUtils(glContext); + + atlas = new WebglAtlas(tilesPerTexture); + + program = utils.createProgram(nodesVS, nodesFS); + gl.useProgram(program); + locations = utils.getLocations(program, ["a_vertexPos", "a_customAttributes", "u_screenSize", "u_transform", "u_sampler0", "u_sampler1", "u_sampler2", "u_sampler3", "u_tilesPerTexture"]); + + gl.uniform1f(locations.tilesPerTexture, tilesPerTexture); + + gl.enableVertexAttribArray(locations.vertexPos); + gl.enableVertexAttribArray(locations.customAttributes); + + buffer = gl.createBuffer(); + } + + function position(nodeUI, pos) { + var idx = nodeUI.id * ATTRIBUTES_PER_PRIMITIVE; + nodes[idx] = pos.x - nodeUI.size; + nodes[idx + 1] = pos.y - nodeUI.size; + nodes[idx + 2] = nodeUI._offset * 4; + + nodes[idx + 3] = pos.x + nodeUI.size; + nodes[idx + 4] = pos.y - nodeUI.size; + nodes[idx + 5] = nodeUI._offset * 4 + 1; + + nodes[idx + 6] = pos.x - nodeUI.size; + nodes[idx + 7] = pos.y + nodeUI.size; + nodes[idx + 8] = nodeUI._offset * 4 + 2; + + nodes[idx + 9] = pos.x - nodeUI.size; + nodes[idx + 10] = pos.y + nodeUI.size; + nodes[idx + 11] = nodeUI._offset * 4 + 2; + + nodes[idx + 12] = pos.x + nodeUI.size; + nodes[idx + 13] = pos.y - nodeUI.size; + nodes[idx + 14] = nodeUI._offset * 4 + 1; + + nodes[idx + 15] = pos.x + nodeUI.size; + nodes[idx + 16] = pos.y + nodeUI.size; + nodes[idx + 17] = nodeUI._offset * 4 + 3; + } + + function createNode(ui) { + nodes = utils.extendArray(nodes, nodesCount, ATTRIBUTES_PER_PRIMITIVE); + nodesCount += 1; + + var coordinates = atlas.getCoordinates(ui.src); + if (coordinates) { + ui._offset = coordinates.offset; + } else { + ui._offset = 0; + // Image is not yet loaded into the atlas. Reload it: + atlas.load(ui.src, function(coordinates) { + ui._offset = coordinates.offset; + }); + } + } + + function removeNode(nodeUI) { + if (nodesCount > 0) { + nodesCount -= 1; + } + + if (nodeUI.id < nodesCount && nodesCount > 0) { + if (nodeUI.src) { + atlas.remove(nodeUI.src); + } + + utils.copyArrayPart(nodes, nodeUI.id * ATTRIBUTES_PER_PRIMITIVE, nodesCount * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); + } + } + + function replaceProperties(replacedNode, newNode) { + newNode._offset = replacedNode._offset; + } + + function updateTransform(newTransform) { + sizeDirty = true; + transform = newTransform; + } + + function updateSize(w, h) { + width = w; + height = h; + sizeDirty = true; + } + + function render() { + gl.useProgram(program); + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData(gl.ARRAY_BUFFER, nodes, gl.DYNAMIC_DRAW); + + if (sizeDirty) { + sizeDirty = false; + gl.uniformMatrix4fv(locations.transform, false, transform); + gl.uniform2f(locations.screenSize, width, height); + } + + gl.vertexAttribPointer(locations.vertexPos, 2, gl.FLOAT, false, 3 * Float32Array.BYTES_PER_ELEMENT, 0); + gl.vertexAttribPointer(locations.customAttributes, 1, gl.FLOAT, false, 3 * Float32Array.BYTES_PER_ELEMENT, 2 * 4); + + ensureAtlasTextureUpdated(); + + gl.drawArrays(gl.TRIANGLES, 0, nodesCount * 6); + } +} + +// TODO: Use glslify for shaders +function createNodeFragmentShader() { + return [ + "precision mediump float;", + "varying vec4 color;", + "varying vec3 vTextureCoord;", + "uniform sampler2D u_sampler0;", + "uniform sampler2D u_sampler1;", + "uniform sampler2D u_sampler2;", + "uniform sampler2D u_sampler3;", + + "void main(void) {", + " if (vTextureCoord.z == 0.) {", + " gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);", + " } else if (vTextureCoord.z == 1.) {", + " gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);", + " } else if (vTextureCoord.z == 2.) {", + " gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);", + " } else if (vTextureCoord.z == 3.) {", + " gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);", + " } else { gl_FragColor = vec4(0, 1, 0, 1); }", + "}" + ].join("\n"); +} + +function createNodeVertexShader() { + return [ + "attribute vec2 a_vertexPos;", + + "attribute float a_customAttributes;", + "uniform vec2 u_screenSize;", + "uniform mat4 u_transform;", + "uniform float u_tilesPerTexture;", + "varying vec3 vTextureCoord;", + + "void main(void) {", + " gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);", + "float corner = mod(a_customAttributes, 4.);", + "float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);", + "float tilesPerRow = sqrt(u_tilesPerTexture);", + "float tileSize = 1./tilesPerRow;", + "float tileColumn = mod(tileIndex, tilesPerRow);", + "float tileRow = floor(tileIndex/tilesPerRow);", + + "if(corner == 0.0) {", + " vTextureCoord.xy = vec2(0, 1);", + "} else if(corner == 1.0) {", + " vTextureCoord.xy = vec2(1, 1);", + "} else if(corner == 2.0) {", + " vTextureCoord.xy = vec2(0, 0);", + "} else {", + " vTextureCoord.xy = vec2(1, 0);", + "}", + + "vTextureCoord *= tileSize;", + "vTextureCoord.x += tileColumn * tileSize;", + "vTextureCoord.y += tileRow * tileSize;", + "vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);", + "}" + ].join("\n"); } From e1b2f0a394f601f8914d477615597d090063dc1a Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 18 Feb 2015 20:59:02 -0800 Subject: [PATCH 165/276] Refactored atlas, removed anonymous functions --- src/WebGL/webglAtlas.js | 347 +++++++++++++++++++++------------------- 1 file changed, 184 insertions(+), 163 deletions(-) diff --git a/src/WebGL/webglAtlas.js b/src/WebGL/webglAtlas.js index d9ebca2..28eb755 100644 --- a/src/WebGL/webglAtlas.js +++ b/src/WebGL/webglAtlas.js @@ -11,171 +11,192 @@ module.exports = webglAtlas; * parameter a new canvas will be created. */ function webglAtlas(tilesPerTexture) { - var tilesPerRow = Math.sqrt(tilesPerTexture || 1024) << 0, - tileSize = tilesPerRow, - lastLoadedIdx = 1, - loadedImages = {}, - dirtyTimeoutId, - skipedDirty = 0, - textures = [], - trackedUrls = [], - that, - - isPowerOf2 = function (n) { - return (n & (n - 1)) === 0; - }, - createTexture = function () { - var texture = new Texture(tilesPerRow * tileSize); - textures.push(texture); - }, - getTileCoordinates = function (absolutePosition) { - var textureNumber = (absolutePosition / tilesPerTexture) << 0, - localTileNumber = (absolutePosition % tilesPerTexture), - row = (localTileNumber / tilesPerRow) << 0, - col = (localTileNumber % tilesPerRow); - - return {textureNumber : textureNumber, row : row, col: col}; - }, - markDirtyNow = function () { - that.isDirty = true; - skipedDirty = 0; - dirtyTimeoutId = null; - }, - markDirty = function () { - // delay this call, since it results in texture reload - if (dirtyTimeoutId) { - window.clearTimeout(dirtyTimeoutId); - skipedDirty += 1; - dirtyTimeoutId = null; - } - - if (skipedDirty > 10) { - markDirtyNow(); - } else { - dirtyTimeoutId = window.setTimeout(markDirtyNow, 400); - } - }, - - copy = function (from, to) { - var fromCanvas = textures[from.textureNumber].canvas, - toCtx = textures[to.textureNumber].ctx, - x = to.col * tileSize, - y = to.row * tileSize; - - toCtx.drawImage(fromCanvas, from.col * tileSize, from.row * tileSize, tileSize, tileSize, x, y, tileSize, tileSize); - textures[from.textureNumber].isDirty = true; - textures[to.textureNumber].isDirty = true; - }, - - drawAt = function (tileNumber, img, callback) { - var tilePosition = getTileCoordinates(tileNumber), - coordinates = { offset : tileNumber }; - - if (tilePosition.textureNumber >= textures.length) { - createTexture(); - } - var currentTexture = textures[tilePosition.textureNumber]; - - currentTexture.ctx.drawImage(img, tilePosition.col * tileSize, tilePosition.row * tileSize, tileSize, tileSize); - trackedUrls[tileNumber] = img.src; - - loadedImages[img.src] = coordinates; - currentTexture.isDirty = true; - - callback(coordinates); - }; - - if (!isPowerOf2(tilesPerTexture)) { - throw "Tiles per texture should be power of two."; + var tilesPerRow = Math.sqrt(tilesPerTexture || 1024) << 0, + tileSize = tilesPerRow, + lastLoadedIdx = 1, + loadedImages = {}, + dirtyTimeoutId, + skipedDirty = 0, + textures = [], + trackedUrls = []; + + if (!isPowerOf2(tilesPerTexture)) { + throw "Tiles per texture should be power of two."; + } + + // this is the return object + var api = { + /** + * indicates whether atlas has changed texture in it. If true then + * some of the textures has isDirty flag set as well. + */ + isDirty: false, + + /** + * Clears any signs of atlas changes. + */ + clearDirty: clearDirty, + + /** + * Removes given url from collection of tiles in the atlas. + */ + remove: remove, + + /** + * Gets all textures in the atlas. + */ + getTextures: getTextures, + + /** + * Gets coordinates of the given image in the atlas. Coordinates is an object: + * {offset : int } - where offset is an absolute position of the image in the + * atlas. + * + * Absolute means it can be larger than tilesPerTexture parameter, and in that + * case clients should get next texture in getTextures() collection. + */ + getCoordinates: getCoordinates, + + /** + * Asynchronously Loads the image to the atlas. Cross-domain security + * limitation applies. + */ + load: load + }; + + return api; + + function clearDirty() { + var i; + api.isDirty = false; + for (i = 0; i < textures.length; ++i) { + textures[i].isDirty = false; } + } - // this is the return object - that = { - /** - * indicates whether atlas has changed texture in it. If true then - * some of the textures has isDirty flag set as well. - */ - isDirty : false, - - /** - * Clears any signs of atlas changes. - */ - clearDirty : function () { - var i; - this.isDirty = false; - for (i = 0; i < textures.length; ++i) { - textures[i].isDirty = false; - } - }, - - /** - * Removes given url from collection of tiles in the atlas. - */ - remove : function (imgUrl) { - var coordinates = loadedImages[imgUrl]; - if (!coordinates) { return false; } - delete loadedImages[imgUrl]; - lastLoadedIdx -= 1; - - - if (lastLoadedIdx === coordinates.offset) { - return true; // Ignore if it's last image in the whole set. - } - - var tileToRemove = getTileCoordinates(coordinates.offset), - lastTileInSet = getTileCoordinates(lastLoadedIdx); - - copy(lastTileInSet, tileToRemove); - - var replacedOffset = loadedImages[trackedUrls[lastLoadedIdx]]; - replacedOffset.offset = coordinates.offset; - trackedUrls[coordinates.offset] = trackedUrls[lastLoadedIdx]; - - markDirty(); - return true; - }, - - /** - * Gets all textures in the atlas. - */ - getTextures : function () { - return textures; // I trust you... - }, - - /** - * Gets coordinates of the given image in the atlas. Coordinates is an object: - * {offset : int } - where offset is an absolute position of the image in the - * atlas. - * - * Absolute means it can be larger than tilesPerTexture parameter, and in that - * case clients should get next texture in getTextures() collection. - */ - getCoordinates : function (imgUrl) { - return loadedImages[imgUrl]; - }, - - /** - * Asynchronously Loads the image to the atlas. Cross-domain security - * limitation applies. - */ - load : function (imgUrl, callback) { - if (loadedImages.hasOwnProperty(imgUrl)) { - callback(loadedImages[imgUrl]); - } else { - var img = new window.Image(), - imgId = lastLoadedIdx; - - lastLoadedIdx += 1; - img.crossOrigin = "anonymous"; - img.onload = function () { - markDirty(); - drawAt(imgId, img, callback); - }; - - img.src = imgUrl; - } - } + function remove(imgUrl) { + var coordinates = loadedImages[imgUrl]; + if (!coordinates) { + return false; + } + delete loadedImages[imgUrl]; + lastLoadedIdx -= 1; + + + if (lastLoadedIdx === coordinates.offset) { + return true; // Ignore if it's last image in the whole set. + } + + var tileToRemove = getTileCoordinates(coordinates.offset), + lastTileInSet = getTileCoordinates(lastLoadedIdx); + + copy(lastTileInSet, tileToRemove); + + var replacedOffset = loadedImages[trackedUrls[lastLoadedIdx]]; + replacedOffset.offset = coordinates.offset; + trackedUrls[coordinates.offset] = trackedUrls[lastLoadedIdx]; + + markDirty(); + return true; + } + + function getTextures() { + return textures; // I trust you... + } + + function getCoordinates(imgUrl) { + return loadedImages[imgUrl]; + } + + function load(imgUrl, callback) { + if (loadedImages.hasOwnProperty(imgUrl)) { + callback(loadedImages[imgUrl]); + } else { + var img = new window.Image(), + imgId = lastLoadedIdx; + + lastLoadedIdx += 1; + img.crossOrigin = "anonymous"; + img.onload = function() { + markDirty(); + drawAt(imgId, img, callback); + }; + + img.src = imgUrl; + } + } + + function createTexture() { + var texture = new Texture(tilesPerRow * tileSize); + textures.push(texture); + } + + function drawAt(tileNumber, img, callback) { + var tilePosition = getTileCoordinates(tileNumber), + coordinates = { + offset: tileNumber + }; + + if (tilePosition.textureNumber >= textures.length) { + createTexture(); + } + var currentTexture = textures[tilePosition.textureNumber]; + + currentTexture.ctx.drawImage(img, tilePosition.col * tileSize, tilePosition.row * tileSize, tileSize, tileSize); + trackedUrls[tileNumber] = img.src; + + loadedImages[img.src] = coordinates; + currentTexture.isDirty = true; + + callback(coordinates); + } + + function getTileCoordinates(absolutePosition) { + var textureNumber = (absolutePosition / tilesPerTexture) << 0, + localTileNumber = (absolutePosition % tilesPerTexture), + row = (localTileNumber / tilesPerRow) << 0, + col = (localTileNumber % tilesPerRow); + + return { + textureNumber: textureNumber, + row: row, + col: col }; + } + + function markDirtyNow() { + api.isDirty = true; + skipedDirty = 0; + dirtyTimeoutId = null; + } + + function markDirty() { + // delay this call, since it results in texture reload + if (dirtyTimeoutId) { + window.clearTimeout(dirtyTimeoutId); + skipedDirty += 1; + dirtyTimeoutId = null; + } + + if (skipedDirty > 10) { + markDirtyNow(); + } else { + dirtyTimeoutId = window.setTimeout(markDirtyNow, 400); + } + } + + function copy(from, to) { + var fromCanvas = textures[from.textureNumber].canvas, + toCtx = textures[to.textureNumber].ctx, + x = to.col * tileSize, + y = to.row * tileSize; + + toCtx.drawImage(fromCanvas, from.col * tileSize, from.row * tileSize, tileSize, tileSize, x, y, tileSize, tileSize); + textures[from.textureNumber].isDirty = true; + textures[to.textureNumber].isDirty = true; + } +} - return that; +function isPowerOf2(n) { + return (n & (n - 1)) === 0; } From 193554aea48d7008c5d5d612045642603da0117f Mon Sep 17 00:00:00 2001 From: anvaka Date: Thu, 19 Feb 2015 17:37:09 -0800 Subject: [PATCH 166/276] Partial removal of anonymous functions --- src/WebGL/webglInputEvents.js | 452 ++++++++++++++++++---------------- 1 file changed, 241 insertions(+), 211 deletions(-) diff --git a/src/WebGL/webglInputEvents.js b/src/WebGL/webglInputEvents.js index 1316b12..a24457f 100644 --- a/src/WebGL/webglInputEvents.js +++ b/src/WebGL/webglInputEvents.js @@ -8,219 +8,249 @@ module.exports = webglInputEvents; * @param {Viva.Graph.View.webglGraphics} webglGraphics */ function webglInputEvents(webglGraphics) { - if (webglGraphics.webglInputEvents) { - // Don't listen twice, if we are already attached to this graphics: - return webglGraphics.webglInputEvents; + if (webglGraphics.webglInputEvents) { + // Don't listen twice, if we are already attached to this graphics: + return webglGraphics.webglInputEvents; + } + + var mouseCapturedNode = null, + mouseEnterCallback = [], + mouseLeaveCallback = [], + mouseDownCallback = [], + mouseUpCallback = [], + mouseMoveCallback = [], + clickCallback = [], + dblClickCallback = [], + prevSelectStart, + boundRect; + + var root = webglGraphics.getGraphicsRoot(); + startListen(root); + + var api = { + mouseEnter: mouseEnter, + mouseLeave: mouseLeave, + mouseDown: mouseDown, + mouseUp: mouseUp, + mouseMove: mouseMove, + click: click, + dblClick: dblClick, + mouseCapture: mouseCapture, + releaseMouseCapture: releaseMouseCapture + }; + + // TODO I don't remember why this is needed: + webglGraphics.webglInputEvents = api; + + return api; + + function releaseMouseCapture() { + mouseCapturedNode = null; + } + + function mouseCapture(node) { + mouseCapturedNode = node; + } + + function dblClick(callback) { + if (typeof callback === 'function') { + dblClickCallback.push(callback); } + return api; + } - var preciseCheck = function (nodeUI, x, y) { - if (nodeUI && nodeUI.size) { - var pos = nodeUI.position, - half = nodeUI.size; - - return pos.x - half < x && x < pos.x + half && - pos.y - half < y && y < pos.y + half; - } - - return true; - }, - getNodeAtClientPos = function (pos) { - return webglGraphics.getNodeAtClientPos(pos, preciseCheck); - }, - mouseCapturedNode = null, - - mouseEnterCallback = [], - mouseLeaveCallback = [], - mouseDownCallback = [], - mouseUpCallback = [], - mouseMoveCallback = [], - clickCallback = [], - dblClickCallback = [], - prevSelectStart, - boundRect, - - stopPropagation = function (e) { - if (e.stopPropagation) { - e.stopPropagation(); - } else { - e.cancelBubble = true; - } - }, - - handleDisabledEvent = function (e) { - stopPropagation(e); - return false; - }, - - invoke = function (callbacksChain, args) { - var i, stopPropagation; - for (i = 0; i < callbacksChain.length; i += 1) { - stopPropagation = callbacksChain[i].apply(undefined, args); - if (stopPropagation) { return true; } - } - }, - - startListen = function (root) { - var pos = {x : 0, y : 0}, - lastFound = null, - lastUpdate = 1, - lastClickTime = +new Date(), - - handleMouseMove = function (e) { - invoke(mouseMoveCallback, [lastFound, e]); - pos.x = e.clientX; - pos.y = e.clientY; - }, - - handleMouseUp = function () { - documentEvents.off('mousemove', handleMouseMove); - documentEvents.off('mouseup', handleMouseUp); - }, - - updateBoundRect = function () { - boundRect = root.getBoundingClientRect(); - }; - - window.addEventListener('resize', updateBoundRect); - updateBoundRect(); - - // mouse move inside container serves only to track mouse enter/leave events. - root.addEventListener('mousemove', - function (e) { - if (mouseCapturedNode) { - return; - } - if (lastUpdate++ % 7 === 0) { - // since there is no bullet proof method to detect resize - // event, we preemptively update the bounding rectangle - updateBoundRect(); - lastUpdate = 1; - } - var cancelBubble = false, - node; - - pos.x = e.clientX - boundRect.left; - pos.y = e.clientY - boundRect.top; - - node = getNodeAtClientPos(pos); - - if (node && lastFound !== node) { - lastFound = node; - cancelBubble = cancelBubble || invoke(mouseEnterCallback, [lastFound]); - } else if (node === null && lastFound !== node) { - cancelBubble = cancelBubble || invoke(mouseLeaveCallback, [lastFound]); - lastFound = null; - } - - if (cancelBubble) { stopPropagation(e); } - }); - - root.addEventListener('mousedown', - function (e) { - var cancelBubble = false, - args; - updateBoundRect(); - pos.x = e.clientX - boundRect.left; - pos.y = e.clientY - boundRect.top; - - args = [getNodeAtClientPos(pos), e]; - if (args[0]) { - cancelBubble = invoke(mouseDownCallback, args); - // we clicked on a node. Following drag should be handled on document events: - documentEvents.on('mousemove', handleMouseMove); - documentEvents.on('mouseup', handleMouseUp); - - prevSelectStart = window.document.onselectstart; - - window.document.onselectstart = handleDisabledEvent; - - lastFound = args[0]; - } else { - lastFound = null; - } - if (cancelBubble) { stopPropagation(e); } - }); - - root.addEventListener('mouseup', - function (e) { - var clickTime = +new Date(), - args; - - pos.x = e.clientX - boundRect.left; - pos.y = e.clientY - boundRect.top; - - args = [getNodeAtClientPos(pos), e]; - if (args[0]) { - window.document.onselectstart = prevSelectStart; - - if (clickTime - lastClickTime < 400 && args[0] === lastFound) { - invoke(dblClickCallback, args); - } else { - invoke(clickCallback, args); - } - lastClickTime = clickTime; - - if (invoke(mouseUpCallback, args)) { - stopPropagation(e); - } - } - }); - }; - - // webgl may not be initialized at this point. Pass callback - // to start listen after graphics root is ready. - webglGraphics.getGraphicsRoot(startListen); - - webglGraphics.webglInputEvents = { - mouseEnter : function (callback) { - if (typeof callback === 'function') { - mouseEnterCallback.push(callback); - } - return this; - }, - mouseLeave : function (callback) { - if (typeof callback === 'function') { - mouseLeaveCallback.push(callback); - } - return this; - }, - mouseDown : function (callback) { - if (typeof callback === 'function') { - mouseDownCallback.push(callback); - } - return this; - }, - mouseUp : function (callback) { - if (typeof callback === 'function') { - mouseUpCallback.push(callback); - } - return this; - }, - mouseMove : function (callback) { - if (typeof callback === 'function') { - mouseMoveCallback.push(callback); - } - return this; - }, - click : function (callback) { - if (typeof callback === 'function') { - clickCallback.push(callback); - } - return this; - }, - dblClick : function (callback) { - if (typeof callback === 'function') { - dblClickCallback.push(callback); - } - return this; - }, - mouseCapture : function (node) { - mouseCapturedNode = node; - }, - releaseMouseCapture : function () { - mouseCapturedNode = null; + function click(callback) { + if (typeof callback === 'function') { + clickCallback.push(callback); + } + return api; + } + + function mouseMove(callback) { + if (typeof callback === 'function') { + mouseMoveCallback.push(callback); + } + return api; + } + + function mouseUp(callback) { + if (typeof callback === 'function') { + mouseUpCallback.push(callback); + } + return api; + } + + function mouseDown(callback) { + if (typeof callback === 'function') { + mouseDownCallback.push(callback); + } + return api; + } + + function mouseLeave(callback) { + if (typeof callback === 'function') { + mouseLeaveCallback.push(callback); + } + return api; + } + + function mouseEnter(callback) { + if (typeof callback === 'function') { + mouseEnterCallback.push(callback); + } + return api; + } + + function preciseCheck(nodeUI, x, y) { + if (nodeUI && nodeUI.size) { + var pos = nodeUI.position, + half = nodeUI.size; + + return pos.x - half < x && x < pos.x + half && + pos.y - half < y && y < pos.y + half; + } + + return true; + } + + function getNodeAtClientPos(pos) { + return webglGraphics.getNodeAtClientPos(pos, preciseCheck); + } + + function stopPropagation(e) { + if (e.stopPropagation) { + e.stopPropagation(); + } else { + e.cancelBubble = true; + } + } + + function handleDisabledEvent(e) { + stopPropagation(e); + return false; + } + + function invoke(callbacksChain, args) { + var i, stopPropagation; + for (i = 0; i < callbacksChain.length; i += 1) { + stopPropagation = callbacksChain[i].apply(undefined, args); + if (stopPropagation) { + return true; + } + } + } + + function startListen(root) { + var pos = { + x: 0, + y: 0 + }, + lastFound = null, + lastUpdate = 1, + lastClickTime = +new Date(), + + handleMouseMove = function(e) { + invoke(mouseMoveCallback, [lastFound, e]); + pos.x = e.clientX; + pos.y = e.clientY; + }, + + handleMouseUp = function() { + documentEvents.off('mousemove', handleMouseMove); + documentEvents.off('mouseup', handleMouseUp); + }, + + updateBoundRect = function() { + boundRect = root.getBoundingClientRect(); + }; + + window.addEventListener('resize', updateBoundRect); + updateBoundRect(); + + // mouse move inside container serves only to track mouse enter/leave events. + root.addEventListener('mousemove', + function(e) { + if (mouseCapturedNode) { + return; + } + if (lastUpdate++ % 7 === 0) { + // since there is no bullet proof method to detect resize + // event, we preemptively update the bounding rectangle + updateBoundRect(); + lastUpdate = 1; } - }; + var cancelBubble = false, + node; - return webglGraphics.webglInputEvents; + pos.x = e.clientX - boundRect.left; + pos.y = e.clientY - boundRect.top; + + node = getNodeAtClientPos(pos); + + if (node && lastFound !== node) { + lastFound = node; + cancelBubble = cancelBubble || invoke(mouseEnterCallback, [lastFound]); + } else if (node === null && lastFound !== node) { + cancelBubble = cancelBubble || invoke(mouseLeaveCallback, [lastFound]); + lastFound = null; + } + + if (cancelBubble) { + stopPropagation(e); + } + }); + + root.addEventListener('mousedown', + function(e) { + var cancelBubble = false, + args; + updateBoundRect(); + pos.x = e.clientX - boundRect.left; + pos.y = e.clientY - boundRect.top; + + args = [getNodeAtClientPos(pos), e]; + if (args[0]) { + cancelBubble = invoke(mouseDownCallback, args); + // we clicked on a node. Following drag should be handled on document events: + documentEvents.on('mousemove', handleMouseMove); + documentEvents.on('mouseup', handleMouseUp); + + prevSelectStart = window.document.onselectstart; + + window.document.onselectstart = handleDisabledEvent; + + lastFound = args[0]; + } else { + lastFound = null; + } + if (cancelBubble) { + stopPropagation(e); + } + }); + + root.addEventListener('mouseup', + function(e) { + var clickTime = +new Date(), + args; + + pos.x = e.clientX - boundRect.left; + pos.y = e.clientY - boundRect.top; + + args = [getNodeAtClientPos(pos), e]; + if (args[0]) { + window.document.onselectstart = prevSelectStart; + + if (clickTime - lastClickTime < 400 && args[0] === lastFound) { + invoke(dblClickCallback, args); + } else { + invoke(clickCallback, args); + } + lastClickTime = clickTime; + + if (invoke(mouseUpCallback, args)) { + stopPropagation(e); + } + } + }); + } } From 887eec08fccfc41b4d7735d25f8af97691bd6a25 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 22 Feb 2015 13:34:23 -0800 Subject: [PATCH 167/276] refactoring, updating to latest simplesvg --- dist/vivagraph.js | 1675 ++++++++++++++++++++++------------------- dist/vivagraph.min.js | 4 +- package.json | 2 +- src/version.js | 2 +- 4 files changed, 895 insertions(+), 788 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 1162de0..31ad651 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -2874,7 +2874,7 @@ module.exports = svg; svg.compile = require('./lib/compile'); -var compileTemplate = svg.compileTemplate = require('./lib/compileTemplate'); +var compileTemplate = svg.compileTemplate = require('./lib/compile_template'); var domEvents = require('add-event-listener'); @@ -2982,7 +2982,7 @@ function augment(element) { } } -},{"./lib/compile":29,"./lib/compileTemplate":30,"add-event-listener":32}],29:[function(require,module,exports){ +},{"./lib/compile":29,"./lib/compile_template":30,"add-event-listener":32}],29:[function(require,module,exports){ var parser = require('./domparser.js'); var svg = require('../'); @@ -4027,80 +4027,91 @@ function Rect (x1, y1, x2, y2) { module.exports = createTimer(); function createTimer() { - var lastTime = 0, - vendors = ['ms', 'moz', 'webkit', 'o'], - i, - scope; - - if (typeof window !== 'undefined') { - scope = window; - } else if (typeof global !== 'undefined') { - scope = global; - } else { - scope = { - setTimeout: function () {}, - clearTimeout: function () {} - }; - } - for (i = 0; i < vendors.length && !scope.requestAnimationFrame; ++i) { - var vendorPrefix = vendors[i]; - scope.requestAnimationFrame = scope[vendorPrefix + 'RequestAnimationFrame']; - scope.cancelAnimationFrame = - scope[vendorPrefix + 'CancelAnimationFrame'] || scope[vendorPrefix + 'CancelRequestAnimationFrame']; - } + var lastTime = 0, + vendors = ['ms', 'moz', 'webkit', 'o'], + i, + scope; + + if (typeof window !== 'undefined') { + scope = window; + } else if (typeof global !== 'undefined') { + scope = global; + } else { + scope = { + setTimeout: noop, + clearTimeout: noop + }; + } - if (!scope.requestAnimationFrame) { - scope.requestAnimationFrame = function (callback) { - var currTime = new Date().getTime(); - var timeToCall = Math.max(0, 16 - (currTime - lastTime)); - var id = scope.setTimeout(function () { callback(currTime + timeToCall); }, timeToCall); - lastTime = currTime + timeToCall; - return id; - }; - } + for (i = 0; i < vendors.length && !scope.requestAnimationFrame; ++i) { + var vendorPrefix = vendors[i]; + scope.requestAnimationFrame = scope[vendorPrefix + 'RequestAnimationFrame']; + scope.cancelAnimationFrame = + scope[vendorPrefix + 'CancelAnimationFrame'] || scope[vendorPrefix + 'CancelRequestAnimationFrame']; + } - if (!scope.cancelAnimationFrame) { - scope.cancelAnimationFrame = function (id) { - scope.clearTimeout(id); - }; - } + if (!scope.requestAnimationFrame) { + scope.requestAnimationFrame = rafPolyfill; + } - return timer; - - /** - * Timer that fires callback with given interval (in ms) until - * callback returns true; - */ - function timer(callback) { - var intervalId, - stopTimer = function () { - scope.cancelAnimationFrame(intervalId); - intervalId = 0; - }, - - startTimer = function () { - intervalId = scope.requestAnimationFrame(startTimer); - if (!callback()) { - stopTimer(); - } - }; + if (!scope.cancelAnimationFrame) { + scope.cancelAnimationFrame = cancelRafPolyfill; + } - startTimer(); // start it right away. + return timer; - return { - /** - * Stops execution of the callback - */ - stop: stopTimer, + /** + * Timer that fires callback with given interval (in ms) until + * callback returns true; + */ + function timer(callback) { + var intervalId; + startTimer(); // start it right away. - restart : function () { - if (!intervalId) { - startTimer(); - } - } - }; + return { + /** + * Stops execution of the callback + */ + stop: stopTimer, + + restart: restart + }; + + function startTimer() { + intervalId = scope.requestAnimationFrame(startTimer); + if (!callback()) { + stopTimer(); + } + } + + function stopTimer() { + scope.cancelAnimationFrame(intervalId); + intervalId = 0; + } + + function restart() { + if (!intervalId) { + startTimer(); + } } + } + + function rafPolyfill(callback) { + var currTime = new Date().getTime(); + var timeToCall = Math.max(0, 16 - (currTime - lastTime)); + var id = scope.setTimeout(function() { + callback(currTime + timeToCall); + }, timeToCall); + lastTime = currTime + timeToCall; + return id; + } + + function cancelRafPolyfill(id) { + scope.clearTimeout(id); + } } + +function noop() {} }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{}],48:[function(require,module,exports){ @@ -5546,98 +5557,101 @@ function Texture(size) { module.exports = webgl; function webgl(gl) { - var createShader = function (shaderText, type) { - var shader = gl.createShader(type); - gl.shaderSource(shader, shaderText); - gl.compileShader(shader); - - if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { - var msg = gl.getShaderInfoLog(shader); - window.alert(msg); - throw msg; - } - return shader; - }; + return { + createProgram: createProgram, + extendArray: extendArray, + copyArrayPart: copyArrayPart, + swapArrayPart: swapArrayPart, + getLocations: getLocations, + context: gl + }; - return { - createProgram : function (vertexShaderSrc, fragmentShaderSrc) { - var program = gl.createProgram(), - vs = createShader(vertexShaderSrc, gl.VERTEX_SHADER), - fs = createShader(fragmentShaderSrc, gl.FRAGMENT_SHADER); - - gl.attachShader(program, vs); - gl.attachShader(program, fs); - gl.linkProgram(program); - - if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { - var msg = gl.getShaderInfoLog(program); - window.alert(msg); - throw msg; - } + function createShader(shaderText, type) { + var shader = gl.createShader(type); + gl.shaderSource(shader, shaderText); + gl.compileShader(shader); - return program; - }, + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + var msg = gl.getShaderInfoLog(shader); + window.alert(msg); + throw msg; + } - extendArray : function (buffer, itemsInBuffer, elementsPerItem) { - if ((itemsInBuffer + 1) * elementsPerItem > buffer.length) { - // Every time we run out of space create new array twice bigger. - // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs - var extendedArray = new Float32Array(buffer.length * elementsPerItem * 2); - extendedArray.set(buffer); + return shader; + } - return extendedArray; - } + function createProgram(vertexShaderSrc, fragmentShaderSrc) { + var program = gl.createProgram(); + var vs = createShader(vertexShaderSrc, gl.VERTEX_SHADER); + var fs = createShader(fragmentShaderSrc, gl.FRAGMENT_SHADER); - return buffer; - }, + gl.attachShader(program, vs); + gl.attachShader(program, fs); + gl.linkProgram(program); - copyArrayPart : function (array, to, from, elementsCount) { - var i; - for (i = 0; i < elementsCount; ++i) { - array[to + i] = array[from + i]; - } - }, + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { + var msg = gl.getShaderInfoLog(program); + window.alert(msg); + throw msg; + } - swapArrayPart : function (array, from, to, elementsCount) { - var i; - for (i = 0; i < elementsCount; ++i) { - var tmp = array[from + i]; - array[from + i] = array[to + i]; - array[to + i] = tmp; - } - }, + return program; + } - getLocations : function (program, uniformOrAttributeNames) { - var foundLocations = {}, - i; - for (i = 0; i < uniformOrAttributeNames.length; ++i) { - var name = uniformOrAttributeNames[i], - location = -1; - if (name.indexOf("a_") === 0) { - location = gl.getAttribLocation(program, name); - if (location === -1) { - throw "Program doesn't have required attribute: " + name; - } + function extendArray(buffer, itemsInBuffer, elementsPerItem) { + if ((itemsInBuffer + 1) * elementsPerItem > buffer.length) { + // Every time we run out of space create new array twice bigger. + // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs + var extendedArray = new Float32Array(buffer.length * elementsPerItem * 2); + extendedArray.set(buffer); - foundLocations[name.slice(2)] = location; - } else if (name.indexOf("u_") === 0) { - location = gl.getUniformLocation(program, name); - if (location === null) { - throw "Program doesn't have required uniform: " + name; - } + return extendedArray; + } - foundLocations[name.slice(2)] = location; - } else { - throw "Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'"; - } - } + return buffer; + } - return foundLocations; - }, + function getLocations(program, uniformOrAttributeNames) { + var foundLocations = {}; + for (var i = 0; i < uniformOrAttributeNames.length; ++i) { + var name = uniformOrAttributeNames[i]; + var location = -1; + if (name[0] === 'a' && name[1] === '_') { + location = gl.getAttribLocation(program, name); + if (location === -1) { + throw new Error("Program doesn't have required attribute: " + name); + } - context : gl - }; + foundLocations[name.slice(2)] = location; + } else if (name[0] === 'u' && name[1] === '_') { + location = gl.getUniformLocation(program, name); + if (location === null) { + throw new Error("Program doesn't have required uniform: " + name); + } + + foundLocations[name.slice(2)] = location; + } else { + throw new Error("Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'"); + } + } + + return foundLocations; + } +} + +function copyArrayPart(array, to, from, elementsCount) { + for (var i = 0; i < elementsCount; ++i) { + array[to + i] = array[from + i]; + } +} + +function swapArrayPart(array, from, to, elementsCount) { + for (var i = 0; i < elementsCount; ++i) { + var tmp = array[from + i]; + array[from + i] = array[to + i]; + array[to + i] = tmp; + } } },{}],55:[function(require,module,exports){ @@ -5654,173 +5668,194 @@ module.exports = webglAtlas; * parameter a new canvas will be created. */ function webglAtlas(tilesPerTexture) { - var tilesPerRow = Math.sqrt(tilesPerTexture || 1024) << 0, - tileSize = tilesPerRow, - lastLoadedIdx = 1, - loadedImages = {}, - dirtyTimeoutId, - skipedDirty = 0, - textures = [], - trackedUrls = [], - that, - - isPowerOf2 = function (n) { - return (n & (n - 1)) === 0; - }, - createTexture = function () { - var texture = new Texture(tilesPerRow * tileSize); - textures.push(texture); - }, - getTileCoordinates = function (absolutePosition) { - var textureNumber = (absolutePosition / tilesPerTexture) << 0, - localTileNumber = (absolutePosition % tilesPerTexture), - row = (localTileNumber / tilesPerRow) << 0, - col = (localTileNumber % tilesPerRow); + var tilesPerRow = Math.sqrt(tilesPerTexture || 1024) << 0, + tileSize = tilesPerRow, + lastLoadedIdx = 1, + loadedImages = {}, + dirtyTimeoutId, + skipedDirty = 0, + textures = [], + trackedUrls = []; + + if (!isPowerOf2(tilesPerTexture)) { + throw "Tiles per texture should be power of two."; + } - return {textureNumber : textureNumber, row : row, col: col}; - }, - markDirtyNow = function () { - that.isDirty = true; - skipedDirty = 0; - dirtyTimeoutId = null; - }, - markDirty = function () { - // delay this call, since it results in texture reload - if (dirtyTimeoutId) { - window.clearTimeout(dirtyTimeoutId); - skipedDirty += 1; - dirtyTimeoutId = null; - } + // this is the return object + var api = { + /** + * indicates whether atlas has changed texture in it. If true then + * some of the textures has isDirty flag set as well. + */ + isDirty: false, - if (skipedDirty > 10) { - markDirtyNow(); - } else { - dirtyTimeoutId = window.setTimeout(markDirtyNow, 400); - } - }, + /** + * Clears any signs of atlas changes. + */ + clearDirty: clearDirty, - copy = function (from, to) { - var fromCanvas = textures[from.textureNumber].canvas, - toCtx = textures[to.textureNumber].ctx, - x = to.col * tileSize, - y = to.row * tileSize; + /** + * Removes given url from collection of tiles in the atlas. + */ + remove: remove, - toCtx.drawImage(fromCanvas, from.col * tileSize, from.row * tileSize, tileSize, tileSize, x, y, tileSize, tileSize); - textures[from.textureNumber].isDirty = true; - textures[to.textureNumber].isDirty = true; - }, + /** + * Gets all textures in the atlas. + */ + getTextures: getTextures, - drawAt = function (tileNumber, img, callback) { - var tilePosition = getTileCoordinates(tileNumber), - coordinates = { offset : tileNumber }; + /** + * Gets coordinates of the given image in the atlas. Coordinates is an object: + * {offset : int } - where offset is an absolute position of the image in the + * atlas. + * + * Absolute means it can be larger than tilesPerTexture parameter, and in that + * case clients should get next texture in getTextures() collection. + */ + getCoordinates: getCoordinates, - if (tilePosition.textureNumber >= textures.length) { - createTexture(); - } - var currentTexture = textures[tilePosition.textureNumber]; + /** + * Asynchronously Loads the image to the atlas. Cross-domain security + * limitation applies. + */ + load: load + }; - currentTexture.ctx.drawImage(img, tilePosition.col * tileSize, tilePosition.row * tileSize, tileSize, tileSize); - trackedUrls[tileNumber] = img.src; + return api; - loadedImages[img.src] = coordinates; - currentTexture.isDirty = true; + function clearDirty() { + var i; + api.isDirty = false; + for (i = 0; i < textures.length; ++i) { + textures[i].isDirty = false; + } + } + + function remove(imgUrl) { + var coordinates = loadedImages[imgUrl]; + if (!coordinates) { + return false; + } + delete loadedImages[imgUrl]; + lastLoadedIdx -= 1; - callback(coordinates); - }; - if (!isPowerOf2(tilesPerTexture)) { - throw "Tiles per texture should be power of two."; + if (lastLoadedIdx === coordinates.offset) { + return true; // Ignore if it's last image in the whole set. } - // this is the return object - that = { - /** - * indicates whether atlas has changed texture in it. If true then - * some of the textures has isDirty flag set as well. - */ - isDirty : false, + var tileToRemove = getTileCoordinates(coordinates.offset), + lastTileInSet = getTileCoordinates(lastLoadedIdx); - /** - * Clears any signs of atlas changes. - */ - clearDirty : function () { - var i; - this.isDirty = false; - for (i = 0; i < textures.length; ++i) { - textures[i].isDirty = false; - } - }, + copy(lastTileInSet, tileToRemove); - /** - * Removes given url from collection of tiles in the atlas. - */ - remove : function (imgUrl) { - var coordinates = loadedImages[imgUrl]; - if (!coordinates) { return false; } - delete loadedImages[imgUrl]; - lastLoadedIdx -= 1; + var replacedOffset = loadedImages[trackedUrls[lastLoadedIdx]]; + replacedOffset.offset = coordinates.offset; + trackedUrls[coordinates.offset] = trackedUrls[lastLoadedIdx]; + markDirty(); + return true; + } - if (lastLoadedIdx === coordinates.offset) { - return true; // Ignore if it's last image in the whole set. - } + function getTextures() { + return textures; // I trust you... + } - var tileToRemove = getTileCoordinates(coordinates.offset), - lastTileInSet = getTileCoordinates(lastLoadedIdx); + function getCoordinates(imgUrl) { + return loadedImages[imgUrl]; + } - copy(lastTileInSet, tileToRemove); + function load(imgUrl, callback) { + if (loadedImages.hasOwnProperty(imgUrl)) { + callback(loadedImages[imgUrl]); + } else { + var img = new window.Image(), + imgId = lastLoadedIdx; + + lastLoadedIdx += 1; + img.crossOrigin = "anonymous"; + img.onload = function() { + markDirty(); + drawAt(imgId, img, callback); + }; - var replacedOffset = loadedImages[trackedUrls[lastLoadedIdx]]; - replacedOffset.offset = coordinates.offset; - trackedUrls[coordinates.offset] = trackedUrls[lastLoadedIdx]; + img.src = imgUrl; + } + } - markDirty(); - return true; - }, + function createTexture() { + var texture = new Texture(tilesPerRow * tileSize); + textures.push(texture); + } - /** - * Gets all textures in the atlas. - */ - getTextures : function () { - return textures; // I trust you... - }, + function drawAt(tileNumber, img, callback) { + var tilePosition = getTileCoordinates(tileNumber), + coordinates = { + offset: tileNumber + }; - /** - * Gets coordinates of the given image in the atlas. Coordinates is an object: - * {offset : int } - where offset is an absolute position of the image in the - * atlas. - * - * Absolute means it can be larger than tilesPerTexture parameter, and in that - * case clients should get next texture in getTextures() collection. - */ - getCoordinates : function (imgUrl) { - return loadedImages[imgUrl]; - }, + if (tilePosition.textureNumber >= textures.length) { + createTexture(); + } + var currentTexture = textures[tilePosition.textureNumber]; - /** - * Asynchronously Loads the image to the atlas. Cross-domain security - * limitation applies. - */ - load : function (imgUrl, callback) { - if (loadedImages.hasOwnProperty(imgUrl)) { - callback(loadedImages[imgUrl]); - } else { - var img = new window.Image(), - imgId = lastLoadedIdx; - - lastLoadedIdx += 1; - img.crossOrigin = "anonymous"; - img.onload = function () { - markDirty(); - drawAt(imgId, img, callback); - }; + currentTexture.ctx.drawImage(img, tilePosition.col * tileSize, tilePosition.row * tileSize, tileSize, tileSize); + trackedUrls[tileNumber] = img.src; - img.src = imgUrl; - } - } + loadedImages[img.src] = coordinates; + currentTexture.isDirty = true; + + callback(coordinates); + } + + function getTileCoordinates(absolutePosition) { + var textureNumber = (absolutePosition / tilesPerTexture) << 0, + localTileNumber = (absolutePosition % tilesPerTexture), + row = (localTileNumber / tilesPerRow) << 0, + col = (localTileNumber % tilesPerRow); + + return { + textureNumber: textureNumber, + row: row, + col: col }; + } + + function markDirtyNow() { + api.isDirty = true; + skipedDirty = 0; + dirtyTimeoutId = null; + } + + function markDirty() { + // delay this call, since it results in texture reload + if (dirtyTimeoutId) { + window.clearTimeout(dirtyTimeoutId); + skipedDirty += 1; + dirtyTimeoutId = null; + } + + if (skipedDirty > 10) { + markDirtyNow(); + } else { + dirtyTimeoutId = window.setTimeout(markDirtyNow, 400); + } + } + + function copy(from, to) { + var fromCanvas = textures[from.textureNumber].canvas, + toCtx = textures[to.textureNumber].ctx, + x = to.col * tileSize, + y = to.row * tileSize; - return that; + toCtx.drawImage(fromCanvas, from.col * tileSize, from.row * tileSize, tileSize, tileSize, x, y, tileSize, tileSize); + textures[from.textureNumber].isDirty = true; + textures[to.textureNumber].isDirty = true; + } +} + +function isPowerOf2(n) { + return (n & (n - 1)) === 0; } },{"./texture.js":53}],56:[function(require,module,exports){ @@ -5872,226 +5907,251 @@ module.exports = webglImageNodeProgram; * Defines simple UI for nodes in webgl renderer. Each node is rendered as an image. */ function webglImageNodeProgram() { - var ATTRIBUTES_PER_PRIMITIVE = 18, - // TODO: Use glslify for shaders - nodesFS = [ - "precision mediump float;", - "varying vec4 color;", - "varying vec3 vTextureCoord;", - "uniform sampler2D u_sampler0;", - "uniform sampler2D u_sampler1;", - "uniform sampler2D u_sampler2;", - "uniform sampler2D u_sampler3;", - - "void main(void) {", - " if (vTextureCoord.z == 0.) {", - " gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);", - " } else if (vTextureCoord.z == 1.) {", - " gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);", - " } else if (vTextureCoord.z == 2.) {", - " gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);", - " } else if (vTextureCoord.z == 3.) {", - " gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);", - " } else { gl_FragColor = vec4(0, 1, 0, 1); }", - "}" - ].join("\n"), - - nodesVS = [ - "attribute vec2 a_vertexPos;", - - "attribute float a_customAttributes;", - "uniform vec2 u_screenSize;", - "uniform mat4 u_transform;", - "uniform float u_tilesPerTexture;", - "varying vec3 vTextureCoord;", - - "void main(void) {", - " gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);", - "float corner = mod(a_customAttributes, 4.);", - "float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);", - "float tilesPerRow = sqrt(u_tilesPerTexture);", - "float tileSize = 1./tilesPerRow;", - "float tileColumn = mod(tileIndex, tilesPerRow);", - "float tileRow = floor(tileIndex/tilesPerRow);", - - "if(corner == 0.0) {", - " vTextureCoord.xy = vec2(0, 1);", - "} else if(corner == 1.0) {", - " vTextureCoord.xy = vec2(1, 1);", - "} else if(corner == 2.0) {", - " vTextureCoord.xy = vec2(0, 0);", - "} else {", - " vTextureCoord.xy = vec2(1, 0);", - "}", - - "vTextureCoord *= tileSize;", - "vTextureCoord.x += tileColumn * tileSize;", - "vTextureCoord.y += tileRow * tileSize;", - "vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);", - "}" - ].join("\n"), - - tilesPerTexture = 1024, // TODO: Get based on max texture size - atlas; - - var program, - gl, - buffer, - utils, - locations, - nodesCount = 0, - nodes = new Float32Array(64), - width, - height, - transform, - sizeDirty, + // WebGL is gian state machine, we store some properties of the state here: + var ATTRIBUTES_PER_PRIMITIVE = 18; + var nodesFS = createNodeFragmentShader(); + var nodesVS = createNodeVertexShader(); + var tilesPerTexture = 1024; // TODO: Get based on max texture size + var atlas; + var program; + var gl; + var buffer; + var utils; + var locations; + var nodesCount = 0; + var nodes = new Float32Array(64); + var width; + var height; + var transform; + var sizeDirty; - refreshTexture = function (texture, idx) { - if (texture.nativeObject) { - gl.deleteTexture(texture.nativeObject); - } - var nativeObject = gl.createTexture(); - gl.activeTexture(gl["TEXTURE" + idx]); - gl.bindTexture(gl.TEXTURE_2D, nativeObject); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.canvas); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST); + return { + load: load, - gl.generateMipmap(gl.TEXTURE_2D); - gl.uniform1i(locations["sampler" + idx], idx); + /** + * Updates position of current node in the buffer of nodes. + * + * @param idx - index of current node. + * @param pos - new position of the node. + */ + position: position, - texture.nativeObject = nativeObject; - }, + createNode: createNode, - ensureAtlasTextureUpdated = function () { - if (atlas.isDirty) { - var textures = atlas.getTextures(), - i; - for (i = 0; i < textures.length; ++i) { - if (textures[i].isDirty || !textures[i].nativeObject) { - refreshTexture(textures[i], i); - } - } + removeNode: removeNode, - atlas.clearDirty(); - } - }; + replaceProperties: replaceProperties, - return { - load : function (glContext) { - gl = glContext; - utils = glUtils(glContext); + updateTransform: updateTransform, - atlas = new WebglAtlas(tilesPerTexture); + updateSize: updateSize, - program = utils.createProgram(nodesVS, nodesFS); - gl.useProgram(program); - locations = utils.getLocations(program, ["a_vertexPos", "a_customAttributes", "u_screenSize", "u_transform", "u_sampler0", "u_sampler1", "u_sampler2", "u_sampler3", "u_tilesPerTexture"]); + render: render + }; - gl.uniform1f(locations.tilesPerTexture, tilesPerTexture); + function refreshTexture(texture, idx) { + if (texture.nativeObject) { + gl.deleteTexture(texture.nativeObject); + } - gl.enableVertexAttribArray(locations.vertexPos); - gl.enableVertexAttribArray(locations.customAttributes); + var nativeObject = gl.createTexture(); + gl.activeTexture(gl["TEXTURE" + idx]); + gl.bindTexture(gl.TEXTURE_2D, nativeObject); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.canvas); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST); - buffer = gl.createBuffer(); - }, + gl.generateMipmap(gl.TEXTURE_2D); + gl.uniform1i(locations["sampler" + idx], idx); - /** - * Updates position of current node in the buffer of nodes. - * - * @param idx - index of current node. - * @param pos - new position of the node. - */ - position : function (nodeUI, pos) { - var idx = nodeUI.id * ATTRIBUTES_PER_PRIMITIVE; - nodes[idx] = pos.x - nodeUI.size; - nodes[idx + 1] = pos.y - nodeUI.size; - nodes[idx + 2] = nodeUI._offset * 4; - - nodes[idx + 3] = pos.x + nodeUI.size; - nodes[idx + 4] = pos.y - nodeUI.size; - nodes[idx + 5] = nodeUI._offset * 4 + 1; - - nodes[idx + 6] = pos.x - nodeUI.size; - nodes[idx + 7] = pos.y + nodeUI.size; - nodes[idx + 8] = nodeUI._offset * 4 + 2; - - nodes[idx + 9] = pos.x - nodeUI.size; - nodes[idx + 10] = pos.y + nodeUI.size; - nodes[idx + 11] = nodeUI._offset * 4 + 2; - - nodes[idx + 12] = pos.x + nodeUI.size; - nodes[idx + 13] = pos.y - nodeUI.size; - nodes[idx + 14] = nodeUI._offset * 4 + 1; - - nodes[idx + 15] = pos.x + nodeUI.size; - nodes[idx + 16] = pos.y + nodeUI.size; - nodes[idx + 17] = nodeUI._offset * 4 + 3; - }, + texture.nativeObject = nativeObject; + } - createNode : function (ui) { - nodes = utils.extendArray(nodes, nodesCount, ATTRIBUTES_PER_PRIMITIVE); - nodesCount += 1; + function ensureAtlasTextureUpdated() { + if (atlas.isDirty) { + var textures = atlas.getTextures(), + i; + for (i = 0; i < textures.length; ++i) { + if (textures[i].isDirty || !textures[i].nativeObject) { + refreshTexture(textures[i], i); + } + } - var coordinates = atlas.getCoordinates(ui.src); - if (coordinates) { - ui._offset = coordinates.offset; - } else { - ui._offset = 0; - // Image is not yet loaded into the atlas. Reload it: - atlas.load(ui.src, function (coordinates) { - ui._offset = coordinates.offset; - }); - } - }, + atlas.clearDirty(); + } + } - removeNode : function (nodeUI) { - if (nodesCount > 0) { nodesCount -= 1; } + function load(glContext) { + gl = glContext; + utils = glUtils(glContext); - if (nodeUI.id < nodesCount && nodesCount > 0) { - if (nodeUI.src) { - atlas.remove(nodeUI.src); - } + atlas = new WebglAtlas(tilesPerTexture); - utils.copyArrayPart(nodes, nodeUI.id * ATTRIBUTES_PER_PRIMITIVE, nodesCount * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); - } - }, + program = utils.createProgram(nodesVS, nodesFS); + gl.useProgram(program); + locations = utils.getLocations(program, ["a_vertexPos", "a_customAttributes", "u_screenSize", "u_transform", "u_sampler0", "u_sampler1", "u_sampler2", "u_sampler3", "u_tilesPerTexture"]); - replaceProperties : function (replacedNode, newNode) { - newNode._offset = replacedNode._offset; - }, + gl.uniform1f(locations.tilesPerTexture, tilesPerTexture); - updateTransform : function (newTransform) { - sizeDirty = true; - transform = newTransform; - }, + gl.enableVertexAttribArray(locations.vertexPos); + gl.enableVertexAttribArray(locations.customAttributes); - updateSize : function (w, h) { - width = w; - height = h; - sizeDirty = true; - }, + buffer = gl.createBuffer(); + } - render : function () { - gl.useProgram(program); - gl.bindBuffer(gl.ARRAY_BUFFER, buffer); - gl.bufferData(gl.ARRAY_BUFFER, nodes, gl.DYNAMIC_DRAW); + function position(nodeUI, pos) { + var idx = nodeUI.id * ATTRIBUTES_PER_PRIMITIVE; + nodes[idx] = pos.x - nodeUI.size; + nodes[idx + 1] = pos.y - nodeUI.size; + nodes[idx + 2] = nodeUI._offset * 4; - if (sizeDirty) { - sizeDirty = false; - gl.uniformMatrix4fv(locations.transform, false, transform); - gl.uniform2f(locations.screenSize, width, height); - } + nodes[idx + 3] = pos.x + nodeUI.size; + nodes[idx + 4] = pos.y - nodeUI.size; + nodes[idx + 5] = nodeUI._offset * 4 + 1; - gl.vertexAttribPointer(locations.vertexPos, 2, gl.FLOAT, false, 3 * Float32Array.BYTES_PER_ELEMENT, 0); - gl.vertexAttribPointer(locations.customAttributes, 1, gl.FLOAT, false, 3 * Float32Array.BYTES_PER_ELEMENT, 2 * 4); + nodes[idx + 6] = pos.x - nodeUI.size; + nodes[idx + 7] = pos.y + nodeUI.size; + nodes[idx + 8] = nodeUI._offset * 4 + 2; - ensureAtlasTextureUpdated(); + nodes[idx + 9] = pos.x - nodeUI.size; + nodes[idx + 10] = pos.y + nodeUI.size; + nodes[idx + 11] = nodeUI._offset * 4 + 2; - gl.drawArrays(gl.TRIANGLES, 0, nodesCount * 6); - } - }; + nodes[idx + 12] = pos.x + nodeUI.size; + nodes[idx + 13] = pos.y - nodeUI.size; + nodes[idx + 14] = nodeUI._offset * 4 + 1; + + nodes[idx + 15] = pos.x + nodeUI.size; + nodes[idx + 16] = pos.y + nodeUI.size; + nodes[idx + 17] = nodeUI._offset * 4 + 3; + } + + function createNode(ui) { + nodes = utils.extendArray(nodes, nodesCount, ATTRIBUTES_PER_PRIMITIVE); + nodesCount += 1; + + var coordinates = atlas.getCoordinates(ui.src); + if (coordinates) { + ui._offset = coordinates.offset; + } else { + ui._offset = 0; + // Image is not yet loaded into the atlas. Reload it: + atlas.load(ui.src, function(coordinates) { + ui._offset = coordinates.offset; + }); + } + } + + function removeNode(nodeUI) { + if (nodesCount > 0) { + nodesCount -= 1; + } + + if (nodeUI.id < nodesCount && nodesCount > 0) { + if (nodeUI.src) { + atlas.remove(nodeUI.src); + } + + utils.copyArrayPart(nodes, nodeUI.id * ATTRIBUTES_PER_PRIMITIVE, nodesCount * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); + } + } + + function replaceProperties(replacedNode, newNode) { + newNode._offset = replacedNode._offset; + } + + function updateTransform(newTransform) { + sizeDirty = true; + transform = newTransform; + } + + function updateSize(w, h) { + width = w; + height = h; + sizeDirty = true; + } + + function render() { + gl.useProgram(program); + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData(gl.ARRAY_BUFFER, nodes, gl.DYNAMIC_DRAW); + + if (sizeDirty) { + sizeDirty = false; + gl.uniformMatrix4fv(locations.transform, false, transform); + gl.uniform2f(locations.screenSize, width, height); + } + + gl.vertexAttribPointer(locations.vertexPos, 2, gl.FLOAT, false, 3 * Float32Array.BYTES_PER_ELEMENT, 0); + gl.vertexAttribPointer(locations.customAttributes, 1, gl.FLOAT, false, 3 * Float32Array.BYTES_PER_ELEMENT, 2 * 4); + + ensureAtlasTextureUpdated(); + + gl.drawArrays(gl.TRIANGLES, 0, nodesCount * 6); + } +} + +// TODO: Use glslify for shaders +function createNodeFragmentShader() { + return [ + "precision mediump float;", + "varying vec4 color;", + "varying vec3 vTextureCoord;", + "uniform sampler2D u_sampler0;", + "uniform sampler2D u_sampler1;", + "uniform sampler2D u_sampler2;", + "uniform sampler2D u_sampler3;", + + "void main(void) {", + " if (vTextureCoord.z == 0.) {", + " gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);", + " } else if (vTextureCoord.z == 1.) {", + " gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);", + " } else if (vTextureCoord.z == 2.) {", + " gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);", + " } else if (vTextureCoord.z == 3.) {", + " gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);", + " } else { gl_FragColor = vec4(0, 1, 0, 1); }", + "}" + ].join("\n"); +} + +function createNodeVertexShader() { + return [ + "attribute vec2 a_vertexPos;", + + "attribute float a_customAttributes;", + "uniform vec2 u_screenSize;", + "uniform mat4 u_transform;", + "uniform float u_tilesPerTexture;", + "varying vec3 vTextureCoord;", + + "void main(void) {", + " gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);", + "float corner = mod(a_customAttributes, 4.);", + "float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);", + "float tilesPerRow = sqrt(u_tilesPerTexture);", + "float tileSize = 1./tilesPerRow;", + "float tileColumn = mod(tileIndex, tilesPerRow);", + "float tileRow = floor(tileIndex/tilesPerRow);", + + "if(corner == 0.0) {", + " vTextureCoord.xy = vec2(0, 1);", + "} else if(corner == 1.0) {", + " vTextureCoord.xy = vec2(1, 1);", + "} else if(corner == 2.0) {", + " vTextureCoord.xy = vec2(0, 0);", + "} else {", + " vTextureCoord.xy = vec2(1, 0);", + "}", + + "vTextureCoord *= tileSize;", + "vTextureCoord.x += tileColumn * tileSize;", + "vTextureCoord.y += tileRow * tileSize;", + "vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);", + "}" + ].join("\n"); } },{"./webgl.js":54,"./webglAtlas.js":55}],58:[function(require,module,exports){ @@ -6105,221 +6165,251 @@ module.exports = webglInputEvents; * @param {Viva.Graph.View.webglGraphics} webglGraphics */ function webglInputEvents(webglGraphics) { - if (webglGraphics.webglInputEvents) { - // Don't listen twice, if we are already attached to this graphics: - return webglGraphics.webglInputEvents; + if (webglGraphics.webglInputEvents) { + // Don't listen twice, if we are already attached to this graphics: + return webglGraphics.webglInputEvents; + } + + var mouseCapturedNode = null, + mouseEnterCallback = [], + mouseLeaveCallback = [], + mouseDownCallback = [], + mouseUpCallback = [], + mouseMoveCallback = [], + clickCallback = [], + dblClickCallback = [], + prevSelectStart, + boundRect; + + var root = webglGraphics.getGraphicsRoot(); + startListen(root); + + var api = { + mouseEnter: mouseEnter, + mouseLeave: mouseLeave, + mouseDown: mouseDown, + mouseUp: mouseUp, + mouseMove: mouseMove, + click: click, + dblClick: dblClick, + mouseCapture: mouseCapture, + releaseMouseCapture: releaseMouseCapture + }; + + // TODO I don't remember why this is needed: + webglGraphics.webglInputEvents = api; + + return api; + + function releaseMouseCapture() { + mouseCapturedNode = null; + } + + function mouseCapture(node) { + mouseCapturedNode = node; + } + + function dblClick(callback) { + if (typeof callback === 'function') { + dblClickCallback.push(callback); } + return api; + } - var preciseCheck = function (nodeUI, x, y) { - if (nodeUI && nodeUI.size) { - var pos = nodeUI.position, - half = nodeUI.size; + function click(callback) { + if (typeof callback === 'function') { + clickCallback.push(callback); + } + return api; + } - return pos.x - half < x && x < pos.x + half && - pos.y - half < y && y < pos.y + half; - } + function mouseMove(callback) { + if (typeof callback === 'function') { + mouseMoveCallback.push(callback); + } + return api; + } - return true; - }, - getNodeAtClientPos = function (pos) { - return webglGraphics.getNodeAtClientPos(pos, preciseCheck); - }, - mouseCapturedNode = null, - - mouseEnterCallback = [], - mouseLeaveCallback = [], - mouseDownCallback = [], - mouseUpCallback = [], - mouseMoveCallback = [], - clickCallback = [], - dblClickCallback = [], - prevSelectStart, - boundRect, + function mouseUp(callback) { + if (typeof callback === 'function') { + mouseUpCallback.push(callback); + } + return api; + } - stopPropagation = function (e) { - if (e.stopPropagation) { - e.stopPropagation(); - } else { - e.cancelBubble = true; - } - }, + function mouseDown(callback) { + if (typeof callback === 'function') { + mouseDownCallback.push(callback); + } + return api; + } - handleDisabledEvent = function (e) { - stopPropagation(e); - return false; - }, + function mouseLeave(callback) { + if (typeof callback === 'function') { + mouseLeaveCallback.push(callback); + } + return api; + } - invoke = function (callbacksChain, args) { - var i, stopPropagation; - for (i = 0; i < callbacksChain.length; i += 1) { - stopPropagation = callbacksChain[i].apply(undefined, args); - if (stopPropagation) { return true; } - } - }, + function mouseEnter(callback) { + if (typeof callback === 'function') { + mouseEnterCallback.push(callback); + } + return api; + } - startListen = function (root) { - var pos = {x : 0, y : 0}, - lastFound = null, - lastUpdate = 1, - lastClickTime = +new Date(), - - handleMouseMove = function (e) { - invoke(mouseMoveCallback, [lastFound, e]); - pos.x = e.clientX; - pos.y = e.clientY; - }, - - handleMouseUp = function () { - documentEvents.off('mousemove', handleMouseMove); - documentEvents.off('mouseup', handleMouseUp); - }, - - updateBoundRect = function () { - boundRect = root.getBoundingClientRect(); - }; + function preciseCheck(nodeUI, x, y) { + if (nodeUI && nodeUI.size) { + var pos = nodeUI.position, + half = nodeUI.size; - window.addEventListener('resize', updateBoundRect); - updateBoundRect(); + return pos.x - half < x && x < pos.x + half && + pos.y - half < y && y < pos.y + half; + } - // mouse move inside container serves only to track mouse enter/leave events. - root.addEventListener('mousemove', - function (e) { - if (mouseCapturedNode) { - return; - } - if (lastUpdate++ % 7 === 0) { - // since there is no bullet proof method to detect resize - // event, we preemptively update the bounding rectangle - updateBoundRect(); - lastUpdate = 1; - } - var cancelBubble = false, - node; + return true; + } - pos.x = e.clientX - boundRect.left; - pos.y = e.clientY - boundRect.top; + function getNodeAtClientPos(pos) { + return webglGraphics.getNodeAtClientPos(pos, preciseCheck); + } - node = getNodeAtClientPos(pos); + function stopPropagation(e) { + if (e.stopPropagation) { + e.stopPropagation(); + } else { + e.cancelBubble = true; + } + } - if (node && lastFound !== node) { - lastFound = node; - cancelBubble = cancelBubble || invoke(mouseEnterCallback, [lastFound]); - } else if (node === null && lastFound !== node) { - cancelBubble = cancelBubble || invoke(mouseLeaveCallback, [lastFound]); - lastFound = null; - } + function handleDisabledEvent(e) { + stopPropagation(e); + return false; + } - if (cancelBubble) { stopPropagation(e); } - }); + function invoke(callbacksChain, args) { + var i, stopPropagation; + for (i = 0; i < callbacksChain.length; i += 1) { + stopPropagation = callbacksChain[i].apply(undefined, args); + if (stopPropagation) { + return true; + } + } + } - root.addEventListener('mousedown', - function (e) { - var cancelBubble = false, - args; - updateBoundRect(); - pos.x = e.clientX - boundRect.left; - pos.y = e.clientY - boundRect.top; + function startListen(root) { + var pos = { + x: 0, + y: 0 + }, + lastFound = null, + lastUpdate = 1, + lastClickTime = +new Date(), - args = [getNodeAtClientPos(pos), e]; - if (args[0]) { - cancelBubble = invoke(mouseDownCallback, args); - // we clicked on a node. Following drag should be handled on document events: - documentEvents.on('mousemove', handleMouseMove); - documentEvents.on('mouseup', handleMouseUp); + handleMouseMove = function(e) { + invoke(mouseMoveCallback, [lastFound, e]); + pos.x = e.clientX; + pos.y = e.clientY; + }, - prevSelectStart = window.document.onselectstart; + handleMouseUp = function() { + documentEvents.off('mousemove', handleMouseMove); + documentEvents.off('mouseup', handleMouseUp); + }, - window.document.onselectstart = handleDisabledEvent; + updateBoundRect = function() { + boundRect = root.getBoundingClientRect(); + }; - lastFound = args[0]; - } else { - lastFound = null; - } - if (cancelBubble) { stopPropagation(e); } - }); - - root.addEventListener('mouseup', - function (e) { - var clickTime = +new Date(), - args; - - pos.x = e.clientX - boundRect.left; - pos.y = e.clientY - boundRect.top; - - args = [getNodeAtClientPos(pos), e]; - if (args[0]) { - window.document.onselectstart = prevSelectStart; - - if (clickTime - lastClickTime < 400 && args[0] === lastFound) { - invoke(dblClickCallback, args); - } else { - invoke(clickCallback, args); - } - lastClickTime = clickTime; - - if (invoke(mouseUpCallback, args)) { - stopPropagation(e); - } - } - }); - }; + window.addEventListener('resize', updateBoundRect); + updateBoundRect(); - // webgl may not be initialized at this point. Pass callback - // to start listen after graphics root is ready. - webglGraphics.getGraphicsRoot(startListen); + // mouse move inside container serves only to track mouse enter/leave events. + root.addEventListener('mousemove', + function(e) { + if (mouseCapturedNode) { + return; + } + if (lastUpdate++ % 7 === 0) { + // since there is no bullet proof method to detect resize + // event, we preemptively update the bounding rectangle + updateBoundRect(); + lastUpdate = 1; + } + var cancelBubble = false, + node; - webglGraphics.webglInputEvents = { - mouseEnter : function (callback) { - if (typeof callback === 'function') { - mouseEnterCallback.push(callback); - } - return this; - }, - mouseLeave : function (callback) { - if (typeof callback === 'function') { - mouseLeaveCallback.push(callback); - } - return this; - }, - mouseDown : function (callback) { - if (typeof callback === 'function') { - mouseDownCallback.push(callback); - } - return this; - }, - mouseUp : function (callback) { - if (typeof callback === 'function') { - mouseUpCallback.push(callback); - } - return this; - }, - mouseMove : function (callback) { - if (typeof callback === 'function') { - mouseMoveCallback.push(callback); - } - return this; - }, - click : function (callback) { - if (typeof callback === 'function') { - clickCallback.push(callback); - } - return this; - }, - dblClick : function (callback) { - if (typeof callback === 'function') { - dblClickCallback.push(callback); - } - return this; - }, - mouseCapture : function (node) { - mouseCapturedNode = node; - }, - releaseMouseCapture : function () { - mouseCapturedNode = null; + pos.x = e.clientX - boundRect.left; + pos.y = e.clientY - boundRect.top; + + node = getNodeAtClientPos(pos); + + if (node && lastFound !== node) { + lastFound = node; + cancelBubble = cancelBubble || invoke(mouseEnterCallback, [lastFound]); + } else if (node === null && lastFound !== node) { + cancelBubble = cancelBubble || invoke(mouseLeaveCallback, [lastFound]); + lastFound = null; } - }; - return webglGraphics.webglInputEvents; + if (cancelBubble) { + stopPropagation(e); + } + }); + + root.addEventListener('mousedown', + function(e) { + var cancelBubble = false, + args; + updateBoundRect(); + pos.x = e.clientX - boundRect.left; + pos.y = e.clientY - boundRect.top; + + args = [getNodeAtClientPos(pos), e]; + if (args[0]) { + cancelBubble = invoke(mouseDownCallback, args); + // we clicked on a node. Following drag should be handled on document events: + documentEvents.on('mousemove', handleMouseMove); + documentEvents.on('mouseup', handleMouseUp); + + prevSelectStart = window.document.onselectstart; + + window.document.onselectstart = handleDisabledEvent; + + lastFound = args[0]; + } else { + lastFound = null; + } + if (cancelBubble) { + stopPropagation(e); + } + }); + + root.addEventListener('mouseup', + function(e) { + var clickTime = +new Date(), + args; + + pos.x = e.clientX - boundRect.left; + pos.y = e.clientY - boundRect.top; + + args = [getNodeAtClientPos(pos), e]; + if (args[0]) { + window.document.onselectstart = prevSelectStart; + + if (clickTime - lastClickTime < 400 && args[0] === lastFound) { + invoke(dblClickCallback, args); + } else { + invoke(clickCallback, args); + } + lastClickTime = clickTime; + + if (invoke(mouseUpCallback, args)) { + stopPropagation(e); + } + } + }); + } } },{"../Utils/documentEvents.js":41}],59:[function(require,module,exports){ @@ -6517,136 +6607,153 @@ module.exports = webglNodeProgram; * Defines simple UI for nodes in webgl renderer. Each node is rendered as square. Color and size can be changed. */ function webglNodeProgram() { - var ATTRIBUTES_PER_PRIMITIVE = 4, // Primitive is point, x, y, size, color - // x, y, z - floats, color = uint. - BYTES_PER_NODE = 3 * Float32Array.BYTES_PER_ELEMENT + Uint32Array.BYTES_PER_ELEMENT, - nodesFS = [ - 'precision mediump float;', - 'varying vec4 color;', + var ATTRIBUTES_PER_PRIMITIVE = 4; // Primitive is point, x, y, size, color + // x, y, z - floats, color = uint. + var BYTES_PER_NODE = 3 * Float32Array.BYTES_PER_ELEMENT + Uint32Array.BYTES_PER_ELEMENT; + var nodesFS = [ + 'precision mediump float;', + 'varying vec4 color;', + + 'void main(void) {', + ' gl_FragColor = color;', + '}' + ].join('\n'); + var nodesVS = [ + 'attribute vec3 a_vertexPos;', + 'attribute vec4 a_color;', + 'uniform vec2 u_screenSize;', + 'uniform mat4 u_transform;', + 'varying vec4 color;', + + 'void main(void) {', + ' gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);', + ' gl_PointSize = a_vertexPos.z * u_transform[0][0];', + ' color = a_color.abgr;', + '}' + ].join('\n'); + + var program; + var gl; + var buffer; + var locations; + var utils; + var storage = new ArrayBuffer(16 * BYTES_PER_NODE); + var positions = new Float32Array(storage); + var colors = new Uint32Array(storage); + var nodesCount = 0; + var width; + var height; + var transform; + var sizeDirty; - 'void main(void) {', - ' gl_FragColor = color;', - '}' - ].join('\n'), - nodesVS = [ - 'attribute vec3 a_vertexPos;', - 'attribute vec4 a_color;', - 'uniform vec2 u_screenSize;', - 'uniform mat4 u_transform;', - 'varying vec4 color;', + return { + load: load, - 'void main(void) {', - ' gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);', - ' gl_PointSize = a_vertexPos.z * u_transform[0][0];', - ' color = a_color.abgr;', - '}' - ].join('\n'), + /** + * Updates position of node in the buffer of nodes. + * + * @param idx - index of current node. + * @param pos - new position of the node. + */ + position: position, - program, - gl, - buffer, - locations, - utils, - storage = new ArrayBuffer(16 * BYTES_PER_NODE), - positions = new Float32Array(storage), - colors = new Uint32Array(storage), - nodesCount = 0, - width, - height, - transform, - sizeDirty, + updateTransform: updateTransform, - ensureEnoughStorage = function () { - if ((nodesCount + 1) * BYTES_PER_NODE >= storage.byteLength) { - // Every time we run out of space create new array twice bigger. - // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs - var extendedStorage = new ArrayBuffer(storage.byteLength * 2), - extendedPositions = new Float32Array(extendedStorage), - extendedColors = new Uint32Array(extendedStorage); + updateSize: updateSize, - extendedColors.set(colors); // should be enough to copy just one view. - positions = extendedPositions; - colors = extendedColors; - storage = extendedStorage; - } - }; + removeNode: removeNode, - return { - load : function (glContext) { - gl = glContext; - utils = glUtils(glContext); + createNode: createNode, - program = utils.createProgram(nodesVS, nodesFS); - gl.useProgram(program); - locations = utils.getLocations(program, ['a_vertexPos', 'a_color', 'u_screenSize', 'u_transform']); + replaceProperties: replaceProperties, - gl.enableVertexAttribArray(locations.vertexPos); - gl.enableVertexAttribArray(locations.color); + render: render + }; - buffer = gl.createBuffer(); - }, + function ensureEnoughStorage() { + if ((nodesCount + 1) * BYTES_PER_NODE >= storage.byteLength) { + // Every time we run out of space create new array twice bigger. + // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs + var extendedStorage = new ArrayBuffer(storage.byteLength * 2), + extendedPositions = new Float32Array(extendedStorage), + extendedColors = new Uint32Array(extendedStorage); + + extendedColors.set(colors); // should be enough to copy just one view. + positions = extendedPositions; + colors = extendedColors; + storage = extendedStorage; + } + } - /** - * Updates position of node in the buffer of nodes. - * - * @param idx - index of current node. - * @param pos - new position of the node. - */ - position : function (nodeUI, pos) { - var idx = nodeUI.id; + function load(glContext) { + gl = glContext; + utils = glUtils(glContext); - positions[idx * ATTRIBUTES_PER_PRIMITIVE] = pos.x; - positions[idx * ATTRIBUTES_PER_PRIMITIVE + 1] = pos.y; - positions[idx * ATTRIBUTES_PER_PRIMITIVE + 2] = nodeUI.size; + program = utils.createProgram(nodesVS, nodesFS); + gl.useProgram(program); + locations = utils.getLocations(program, ['a_vertexPos', 'a_color', 'u_screenSize', 'u_transform']); - colors[idx * ATTRIBUTES_PER_PRIMITIVE + 3] = nodeUI.color; - }, + gl.enableVertexAttribArray(locations.vertexPos); + gl.enableVertexAttribArray(locations.color); - updateTransform : function (newTransform) { - sizeDirty = true; - transform = newTransform; - }, + buffer = gl.createBuffer(); + } - updateSize : function (w, h) { - width = w; - height = h; - sizeDirty = true; - }, + function position(nodeUI, pos) { + var idx = nodeUI.id; - removeNode : function (node) { - if (nodesCount > 0) { nodesCount -= 1; } + positions[idx * ATTRIBUTES_PER_PRIMITIVE] = pos.x; + positions[idx * ATTRIBUTES_PER_PRIMITIVE + 1] = pos.y; + positions[idx * ATTRIBUTES_PER_PRIMITIVE + 2] = nodeUI.size; - if (node.id < nodesCount && nodesCount > 0) { - // we can use colors as a 'view' into array array buffer. - utils.copyArrayPart(colors, node.id * ATTRIBUTES_PER_PRIMITIVE, nodesCount * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); - } - }, -/*jshint unused:false */ - createNode : function (node) { - ensureEnoughStorage(); - nodesCount += 1; - }, + colors[idx * ATTRIBUTES_PER_PRIMITIVE + 3] = nodeUI.color; + } - replaceProperties : function (replacedNode, newNode) {}, -/*jshint unused:true */ + function updateTransform(newTransform) { + sizeDirty = true; + transform = newTransform; + } - render : function () { - gl.useProgram(program); - gl.bindBuffer(gl.ARRAY_BUFFER, buffer); - gl.bufferData(gl.ARRAY_BUFFER, storage, gl.DYNAMIC_DRAW); + function updateSize(w, h) { + width = w; + height = h; + sizeDirty = true; + } - if (sizeDirty) { - sizeDirty = false; - gl.uniformMatrix4fv(locations.transform, false, transform); - gl.uniform2f(locations.screenSize, width, height); - } + function removeNode(node) { + if (nodesCount > 0) { + nodesCount -= 1; + } - gl.vertexAttribPointer(locations.vertexPos, 3, gl.FLOAT, false, ATTRIBUTES_PER_PRIMITIVE * Float32Array.BYTES_PER_ELEMENT, 0); - gl.vertexAttribPointer(locations.color, 4, gl.UNSIGNED_BYTE, true, ATTRIBUTES_PER_PRIMITIVE * Float32Array.BYTES_PER_ELEMENT, 3 * 4); + if (node.id < nodesCount && nodesCount > 0) { + // we can use colors as a 'view' into array array buffer. + utils.copyArrayPart(colors, node.id * ATTRIBUTES_PER_PRIMITIVE, nodesCount * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); + } + } - gl.drawArrays(gl.POINTS, 0, nodesCount); - } - }; + function createNode() { + ensureEnoughStorage(); + nodesCount += 1; + } + + function replaceProperties(/* replacedNode, newNode */) {} + + function render() { + gl.useProgram(program); + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData(gl.ARRAY_BUFFER, storage, gl.DYNAMIC_DRAW); + + if (sizeDirty) { + sizeDirty = false; + gl.uniformMatrix4fv(locations.transform, false, transform); + gl.uniform2f(locations.screenSize, width, height); + } + + gl.vertexAttribPointer(locations.vertexPos, 3, gl.FLOAT, false, ATTRIBUTES_PER_PRIMITIVE * Float32Array.BYTES_PER_ELEMENT, 0); + gl.vertexAttribPointer(locations.color, 4, gl.UNSIGNED_BYTE, true, ATTRIBUTES_PER_PRIMITIVE * Float32Array.BYTES_PER_ELEMENT, 3 * 4); + + gl.drawArrays(gl.POINTS, 0, nodesCount); + } } },{"./webgl.js":54}],62:[function(require,module,exports){ @@ -6676,7 +6783,7 @@ function webglSquare(size, color) { } },{"./parseColor.js":52}],63:[function(require,module,exports){ -module.exports = '0.7.2'; +module.exports = '0.7.3'; },{}]},{},[1])(1) }); \ No newline at end of file diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index a5800fe..18060e0 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,s){if(!t[a]){if(!n[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=s-i,d=o-a,p=a*i-o*s,v=f*e+d*n+p,h=f*t+d*r+p,0!==v&&0!==h&&v>=0==h>=0?null:(y=u*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-u*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=t},{}],3:[function(e,n){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n){function t(e,n){function t(e){h[e]/=2}function r(e){h[e.id]=0}function o(e){u=e.id,s(u),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function h(e){var n=w[e];n.mass=y(e)}function g(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function m(e){var n=w[e];return n||(c(e),n=w[e]),n}function y(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var x=e("ngraph.physics.simulator");t=t||x(),o(t,"physicsSimulator").has("step","getBestNewBodyPosition","addBodyAt");var w="function"==typeof Object.create?Object.create(null):{},b={},E=t.settings.springTransform||r;f(),s();var L={step:function(){return t.step()},getNodePosition:function(e){return m(e).pos},setNodePosition:function(e){var n=m(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return t.getBBox()},pinNode:function(e,n){var t=m(e.id);t.isPinned=!!n},isNodePinned:function(e){return m(e.id).isPinned},dispose:function(){n.off("changed",u)},getBody:a,getSpring:i,simulator:t};return L}function r(){}n.exports=t,n.exports.simulator=e("ngraph.physics.simulator");var o=e("varta")},{"ngraph.physics.simulator":8,varta:21}],8:[function(e,n){function t(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.force.reset(),v.updateBodyForce(e),m.update(e);for(n=p.length;n--;)g.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),s=n.createBounds||e("./lib/bounds"),u=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),h=s(l,n),g=f(n),m=u(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return h.update(),en))return l.splice(n,1),0===l.length&&h.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return h.getBestNewPosition(e)},getBBox:function(){return h.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=t},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":25,"ngraph.quadtreebh":17}],9:[function(e,n){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var s=n[e];s.isPinned?(s.pos.x=s.prevPos.x,s.pos.y=s.prevPos.y):(s.prevPos.x=s.pos.x,s.prevPos.y=s.pos.y),s.pos.xo&&(o=s.pos.x),s.pos.ya&&(a=s.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var s=0;st;++t){var u=e[t],f=n/u.mass;u.velocity.x+=f*u.force.x,u.velocity.y+=f*u.force.y;var c=u.velocity.x,d=u.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(u.velocity.x=c/l,u.velocity.y=d/l),r=n*u.velocity.x,i=n*u.velocity.y,u.pos.x+=r,u.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=t},{}],13:[function(e,n){function t(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=t},{}],14:[function(e,n){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,s=o.pos.y-t.pos.y,u=Math.sqrt(a*a+s*s);0===u&&(a=(r.nextDouble()-.5)/50,s=(r.nextDouble()-.5)/50,u=Math.sqrt(a*a+s*s));var f=u-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/u*e.weight;t.force.x+=c*a,t.force.y+=c*s,o.force.x-=c*a,o.force.y-=c*s}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":25,"ngraph.random":26}],15:[function(e,n){function t(e,n,t){var o="[object Array]"===Object.prototype.toString.call(t);if(o)for(var i=0;i0&&i(a.pos,o.pos));if(0===s&&i(a.pos,o.pos))return}u.push(r,a),u.push(r,o)}else{var v=o.pos.x,h=o.pos.y;r.mass=r.mass+o.mass,r.massX=r.massX+o.mass*v,r.massY=r.massY+o.mass*h;var g=0,m=r.left,y=(r.right+m)/2,x=r.top,w=(r.bottom+x)/2;if(v>y){g+=1;var b=m;m=y,y+=y-b}if(h>w){g+=2;var E=x;x=w,w+=w-E}var L=r.quads[g];L?u.push(L,o):(L=l(),L.left=m,L.top=x,L.right=y,L.bottom=w,L.body=o,r.quads[g]=L)}}},h=function(e){var n,r,o,i,u=s,c=0,d=0,l=1,v=0,h=1;for(u[0]=p;l;){var g=u[v],m=g.body;l-=1,v+=1,m&&m!==e?(r=m.pos.x-e.pos.x,o=m.pos.y-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),n=a*m.mass*e.mass/(i*i*i),c+=n*r,d+=n*o):(r=g.massX/g.mass-e.pos.x,o=g.massY/g.mass-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),(g.right-g.left)/is&&(t=s),s>o&&(o=s),r>u&&(r=u),u>i&&(i=u)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,d=0,p=l(),p.left=t,p.right=o,p.top=r,p.bottom=i,n=a-1,n>0&&(p.body=e[n]);n--;)v(e[n],p)};return{insertBodies:g,updateBodyForce:h,options:function(e){return e?("number"==typeof e.gravity&&(a=e.gravity),"number"==typeof e.theta&&(f=e.theta),this):{gravity:a,theta:f}}}}},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":26}],18:[function(e,n){function t(){this.stack=[],this.popIdx=0}function r(e,n){this.node=e,this.body=n}n.exports=t,t.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new r(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],19:[function(e,n){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],20:[function(e,n){n.exports=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],21:[function(e,n){function t(e,n){function t(){return o(e,n,arguments)}return n=n||"Argument",{has:t}}function r(){function e(e,t){return o(e,t,n)}var n=arguments;return e}function o(e,n,t){if(void 0===e)throw new Error(n+" is not defined");for(var r=0;re)throw new Error("Invalid number of nodes");var n,t=l();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function r(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=t(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function o(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=l();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function i(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=l();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function a(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=l();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function s(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=l();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function u(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=l();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var s=i*e*n,u=r+o*e+s;r>0&&a.addLink(u,r-1+o*e+s),o>0&&a.addLink(u,r+(o-1)*e+s),i>0&&a.addLink(u,r+o*e+(i-1)*e*n)}return a}function f(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=l(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function c(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=l();for(n=0;e>n;++n)t.addNode(n);return t}function d(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,s=e("ngraph.random").random(o||42),u=l();for(i=0;n>i;++i)u.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,u.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(s.nextDouble()n)return!1;S(),P.splice(n,1);var t=u(e.fromId),o=u(e.toId);return t&&(n=r(e,t.links),n>=0&&t.links.splice(n,1)),o&&(n=r(e,o.links),n>=0&&o.links.splice(n,1)),T(e,"remove"),D(),!0}function p(e,n){var t,r=u(e);if(!r)return null;for(t=0;tn;++n)e(P[n])}function g(e,n,t){var r,o,i,a=u(e);if(a&&a.links&&"function"==typeof n)if(t)for(r=0;r0&&(M.fire("changed",I),I.length=0)}function w(){return Object.keys?b:E}function b(e){if("function"==typeof e)for(var n=Object.keys(L),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function o(e){this.id=e,this.links=[],this.data=null}function i(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=t;var a=e("ngraph.events")},{"ngraph.events":6}],25:[function(e,n){function t(e,n){var r;if(e||(e={}),n)for(r in n)if(n.hasOwnProperty(r)){var o=e.hasOwnProperty(r),i=typeof n[r],a=!o||typeof e[r]!==i;a?e[r]=n[r]:"object"===i&&(e[r]=t(e[r],n[r]))}return e}n.exports=t},{}],26:[function(e,n){function t(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function r(e,n){var r=n||t();if("function"!=typeof r.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var t,o,i;for(t=e.length-1;t>0;--t)o=r.next(t+1),i=e[o],e[o]=e[t],e[t]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,t,o;for(n=e.length-1;n>0;--n)t=r.next(n+1),o=e[t],e[t]=e[n],e[n]=o;return e}}}n.exports={random:t,randomIterator:r}},{}],27:[function(e,n){function t(e,n,t){function r(e){s.nodes.push(u(e))}function o(e){s.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var s={nodes:[],links:[]},u=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(s)}n.exports=t},{}],28:[function(e,n){function t(e,n){var t=r(e);if(void 0===n)return t;for(var o=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),s(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},k=function(e){p=!1,r.off("touchmove",A),r.off("touchend",k),r.off("touchcancel",k),c=null,a&&a(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,r.on("touchmove",A),r.on("touchend",k),r.on("touchcancel",k))},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return a=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),r.off("mousemove",w),r.off("mouseup",E),r.off("touchmove",A),r.off("touchend",k),r.off("touchcancel",k),P(null) -}}}n.exports=t;var r=e("../Utils/documentEvents.js"),o=e("../Utils/browserInfo.js"),i=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":40,"../Utils/documentEvents.js":41,"../Utils/findElementPosition.js":42}],37:[function(e,n){function t(e,n){var t=r(n),o=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){o=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(o);var r=i[e.id];return r&&r.onStart&&r.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(o),o=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(o){var t=i[o.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=t;var r=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":58}],38:[function(e,n){function t(e,n){function t(e){return d[e]}n=r(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var a=o(n.seed),s=new i(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),u={},f=function(){return{x:a.next(n.maxX),y:a.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],s)},p=function(){0!==e.getNodesCount()&&(s.x1=Number.MAX_VALUE,s.y1=Number.MAX_VALUE,s.x2=Number.MIN_VALUE,s.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){u[e.id]=e},h=function(e){for(var n=0;n0)for(e=0;en,t)}),e.forEachNode(O),H(),e.on("changed",q)},K=function(){y=!1,H(),W(),a.off("resize",V),j.removeAllListeners(),l.stop(),e.forEachLink(function(e){n.renderLinks&&B(e)}),e.forEachNode(function(e){F(e),U(e)}),v.dispose(),z()};return{run:function(e){return y||(k(),S(),D(),G(),$(),y=!0),T(e),this},reset:function(){h.resetScale(),D(),A.scale=1},pause:function(){P=!0,l.stop()},resume:function(){P=!1,l.restart()},rerender:function(){return _(),this},zoomOut:function(){return J(!0)},zoomIn:function(){return J(!1)},moveTo:function(e,n){h.graphCenterChanged(A.offsetX-e*A.scale,A.offsetY-n*A.scale),_()},getGraphics:function(){return h},dispose:function(){K()},on:function(e,n){return j.addEventListener(e,n),this},off:function(e,n){return j.removeEventListener(e,n),this}}}n.exports=t;var r=e("ngraph.graph"),o=e("ngraph.forcelayout"),i=e("./svgGraphics.js"),a=e("../Utils/windowEvents.js"),s=e("../Input/domInputManager.js"),u=e("../Utils/timer.js"),f=e("../Utils/getDimensions.js"),c=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.forcelayout":7,"ngraph.graph":24}],50:[function(e,n){function t(){function e(){var e=r("svg");return n=r("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,a,s,u,f=1,c={},d={},l=function(){return r("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(){return r("line").attr("stroke","#999")},h=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},g=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+a+","+s+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return h=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){a=e,s=n,w()},inputManager:i,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var s="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",s)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),u=n.getCTM().multiply(i);f=u.a,a=u.e,s=u.f;var c="matrix("+u.a+", 0, 0,"+u.d+","+u.e+","+u.f+")";return n.attr("transform",c),g(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),g(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof u&&u(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,h(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):u=e),t},getSvgRoot:function(){return t}};return o(b),b}n.exports=t;var r=e("simplesvg"),o=e("ngraph.events"),i=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":35,"ngraph.events":6,simplesvg:28}],51:[function(e,n){function t(e){e=f(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,c,d,l,p,v,h,g=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=o(),P=i(),N=function(){return a()},A=function(){return s(3014898687)},k=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),c&&c.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(A=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:r,beginRender:function(){},endRender:function(){m>0&&L.render(),g>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,k()},addLink:function(e,n){var t=m++,r=A(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=g++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],k()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,k(),I(this),y[0]},resetScale:function(){return j(),c&&(_(),k()),this},init:function(r){var o={};if(e.preserveDrawingBuffer&&(o.preserveDrawingBuffer=!0),n=r,_(),j(),n.appendChild(t),c=t.getContext("experimental-webgl",o),!c){var i="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(i),i}if(e.enableBlending&&(c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA),c.enable(c.BLEND)),e.clearColor){var a=e.clearColorValue;c.clearColor(a.r,a.g,a.b,a.a),this.beginRender=function(){c.clear(c.COLOR_BUFFER_BIT)}}L.load(c),L.updateSize(d/2,l/2),P.load(c),P.updateSize(d/2,l/2),k(),"function"==typeof h&&h(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){g>0&&(g-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(g>t){if(0===g||g===t)return;var r=x[g];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;g>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):h=e),t},setNodeProgram:function(e){if(!c&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!c&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;g>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return u(T),T}n.exports=t;var r=e("../Input/webglInputManager.js"),o=e("../WebGL/webglLinkProgram.js"),i=e("../WebGL/webglNodeProgram.js"),a=e("../WebGL/webglSquare.js"),s=e("../WebGL/webglLine.js"),u=e("ngraph.events"),f=e("ngraph.merge")},{"../Input/webglInputManager.js":37,"../WebGL/webglLine.js":59,"../WebGL/webglLinkProgram.js":60,"../WebGL/webglNodeProgram.js":61,"../WebGL/webglSquare.js":62,"ngraph.events":6,"ngraph.merge":25}],52:[function(e,n){function t(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=t},{}],53:[function(e,n){function t(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=t},{}],54:[function(e,n){function t(e){var n=function(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r};return{createProgram:function(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var s=e.getShaderInfoLog(o);throw window.alert(s),s}return o},extendArray:function(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e},copyArrayPart:function(e,n,t,r){var o;for(o=0;r>o;++o)e[n+o]=e[t+o]},swapArrayPart:function(e,n,t,r){var o;for(o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}},getLocations:function(n,t){var r,o={};for(r=0;r10?v():n=window.setTimeout(v,400)},g=function(e,n){var t=f[e.textureNumber].canvas,r=f[n.textureNumber].ctx,o=n.col*i,a=n.row*i;r.drawImage(t,e.col*i,e.row*i,i,i,o,a,i,i),f[e.textureNumber].isDirty=!0,f[n.textureNumber].isDirty=!0},m=function(e,n,t){var r=p(e),o={offset:e};r.textureNumber>=f.length&&l();var a=f[r.textureNumber];a.ctx.drawImage(n,r.col*i,r.row*i,i,i),c[e]=n.src,s[n.src]=o,a.isDirty=!0,t(o)};if(!d(e))throw"Tiles per texture should be power of two.";return t={isDirty:!1,clearDirty:function(){var e;for(this.isDirty=!1,e=0;e0&&(g-=1),n.id0&&(n.src&&e.remove(n.src),a.copyArrayPart(m,n.id*l,g*l,l))},replaceProperties:function(e,n){n._offset=e._offset},updateTransform:function(e){d=!0,c=e},updateSize:function(e,n){u=e,f=n,d=!0},render:function(){t.useProgram(n),t.bindBuffer(t.ARRAY_BUFFER,i),t.bufferData(t.ARRAY_BUFFER,m,t.DYNAMIC_DRAW),d&&(d=!1,t.uniformMatrix4fv(s.transform,!1,c),t.uniform2f(s.screenSize,u,f)),t.vertexAttribPointer(s.vertexPos,2,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(s.customAttributes,1,t.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),x(),t.drawArrays(t.TRIANGLES,0,6*g)}}}var r=e("./webglAtlas.js"),o=e("./webgl.js");n.exports=t},{"./webgl.js":54,"./webglAtlas.js":55}],58:[function(e,n){function t(e){if(e.webglInputEvents)return e.webglInputEvents;var n,t,o=function(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oa-x&&r[0]===m?g(p,r):g(l,r),x=a,g(c,r)&&v(e))})};return e.getGraphicsRoot(m),e.webglInputEvents={mouseEnter:function(e){return"function"==typeof e&&s.push(e),this},mouseLeave:function(e){return"function"==typeof e&&u.push(e),this},mouseDown:function(e){return"function"==typeof e&&f.push(e),this},mouseUp:function(e){return"function"==typeof e&&c.push(e),this},mouseMove:function(e){return"function"==typeof e&&d.push(e),this},click:function(e){return"function"==typeof e&&l.push(e),this},dblClick:function(e){return"function"==typeof e&&p.push(e),this},mouseCapture:function(e){a=e},releaseMouseCapture:function(){a=null}},e.webglInputEvents}var r=e("../Utils/documentEvents.js");n.exports=t},{"../Utils/documentEvents.js":41}],59:[function(e,n){function t(e){return{color:r(e)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],60:[function(e,n){function t(){var e,n,t,o,i,a,s,u,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),h=0,g=new ArrayBuffer(16*l),m=new Float32Array(g),y=new Uint32Array(g),x=function(){if((h+1)*l>g.byteLength){var e=new ArrayBuffer(2*g.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,g=e}};return{load:function(a){n=a,o=r(a),e=o.createProgram(v,p),n.useProgram(e),i=o.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),h+=1,a=e.id},removeLink:function(e){h>0&&(h-=1),e.id0&&o.copyArrayPart(y,e.id*d,h*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){s=e,u=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,g,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,s,u)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*h),a=h-1},bringToFront:function(e){a>e.id&&o.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],61:[function(e,n){function t(){var e,n,t,o,i,a,s,u,f,c=4,d=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,l=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),p=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),v=new ArrayBuffer(16*d),h=new Float32Array(v),g=new Uint32Array(v),m=0,y=function(){if((m+1)*d>=v.byteLength){var e=new ArrayBuffer(2*v.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(g),h=n,g=t,v=e}};return{load:function(a){n=a,i=r(a),e=i.createProgram(p,l),n.useProgram(e),o=i.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(o.vertexPos),n.enableVertexAttribArray(o.color),t=n.createBuffer()},position:function(e,n){var t=e.id;h[t*c]=n.x,h[t*c+1]=n.y,h[t*c+2]=e.size,g[t*c+3]=e.color},updateTransform:function(e){f=!0,u=e},updateSize:function(e,n){a=e,s=n,f=!0},removeNode:function(e){m>0&&(m-=1),e.id0&&i.copyArrayPart(g,e.id*c,m*c,c)},createNode:function(){y(),m+=1},replaceProperties:function(){},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,v,n.DYNAMIC_DRAW),f&&(f=!1,n.uniformMatrix4fv(o.transform,!1,u),n.uniform2f(o.screenSize,a,s)),n.vertexAttribPointer(o.vertexPos,3,n.FLOAT,!1,c*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(o.color,4,n.UNSIGNED_BYTE,!0,c*Float32Array.BYTES_PER_ELEMENT,12),n.drawArrays(n.POINTS,0,m)}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],62:[function(e,n){function t(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],63:[function(e,n){n.exports="0.7.2"},{}]},{},[1])(1)}); \ No newline at end of file +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,s){if(!t[a]){if(!n[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=s-i,d=o-a,p=a*i-o*s,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=u*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-u*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=t},{}],3:[function(e,n){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n){function t(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){u=e.id,s(u),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function g(e){var n=w[e];n.mass=y(e)}function h(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function m(e){var n=w[e];return n||(c(e),n=w[e]),n}function y(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var x=e("ngraph.physics.simulator");t=t||x(),o(t,"physicsSimulator").has("step","getBestNewBodyPosition","addBodyAt");var w="function"==typeof Object.create?Object.create(null):{},b={},E=t.settings.springTransform||r;f(),s();var L={step:function(){return t.step()},getNodePosition:function(e){return m(e).pos},setNodePosition:function(e){var n=m(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return t.getBBox()},pinNode:function(e,n){var t=m(e.id);t.isPinned=!!n},isNodePinned:function(e){return m(e.id).isPinned},dispose:function(){n.off("changed",u)},getBody:a,getSpring:i,simulator:t};return L}function r(){}n.exports=t,n.exports.simulator=e("ngraph.physics.simulator");var o=e("varta")},{"ngraph.physics.simulator":8,varta:21}],8:[function(e,n){function t(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.force.reset(),v.updateBodyForce(e),m.update(e);for(n=p.length;n--;)h.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),s=n.createBounds||e("./lib/bounds"),u=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),g=s(l,n),h=f(n),m=u(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return g.update(),en))return l.splice(n,1),0===l.length&&g.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return g.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=t},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":25,"ngraph.quadtreebh":17}],9:[function(e,n){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var s=n[e];s.isPinned?(s.pos.x=s.prevPos.x,s.pos.y=s.prevPos.y):(s.prevPos.x=s.pos.x,s.prevPos.y=s.pos.y),s.pos.xo&&(o=s.pos.x),s.pos.ya&&(a=s.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var s=0;st;++t){var u=e[t],f=n/u.mass;u.velocity.x+=f*u.force.x,u.velocity.y+=f*u.force.y;var c=u.velocity.x,d=u.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(u.velocity.x=c/l,u.velocity.y=d/l),r=n*u.velocity.x,i=n*u.velocity.y,u.pos.x+=r,u.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=t},{}],13:[function(e,n){function t(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=t},{}],14:[function(e,n){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,s=o.pos.y-t.pos.y,u=Math.sqrt(a*a+s*s);0===u&&(a=(r.nextDouble()-.5)/50,s=(r.nextDouble()-.5)/50,u=Math.sqrt(a*a+s*s));var f=u-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/u*e.weight;t.force.x+=c*a,t.force.y+=c*s,o.force.x-=c*a,o.force.y-=c*s}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":25,"ngraph.random":26}],15:[function(e,n){function t(e,n,t){var o="[object Array]"===Object.prototype.toString.call(t);if(o)for(var i=0;i0&&i(a.pos,o.pos));if(0===s&&i(a.pos,o.pos))return}u.push(r,a),u.push(r,o)}else{var v=o.pos.x,g=o.pos.y;r.mass=r.mass+o.mass,r.massX=r.massX+o.mass*v,r.massY=r.massY+o.mass*g;var h=0,m=r.left,y=(r.right+m)/2,x=r.top,w=(r.bottom+x)/2;if(v>y){h+=1;var b=m;m=y,y+=y-b}if(g>w){h+=2;var E=x;x=w,w+=w-E}var L=r.quads[h];L?u.push(L,o):(L=l(),L.left=m,L.top=x,L.right=y,L.bottom=w,L.body=o,r.quads[h]=L)}}},g=function(e){var n,r,o,i,u=s,c=0,d=0,l=1,v=0,g=1;for(u[0]=p;l;){var h=u[v],m=h.body;l-=1,v+=1,m&&m!==e?(r=m.pos.x-e.pos.x,o=m.pos.y-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),n=a*m.mass*e.mass/(i*i*i),c+=n*r,d+=n*o):(r=h.massX/h.mass-e.pos.x,o=h.massY/h.mass-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),(h.right-h.left)/is&&(t=s),s>o&&(o=s),r>u&&(r=u),u>i&&(i=u)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,d=0,p=l(),p.left=t,p.right=o,p.top=r,p.bottom=i,n=a-1,n>0&&(p.body=e[n]);n--;)v(e[n],p)};return{insertBodies:h,updateBodyForce:g,options:function(e){return e?("number"==typeof e.gravity&&(a=e.gravity),"number"==typeof e.theta&&(f=e.theta),this):{gravity:a,theta:f}}}}},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":26}],18:[function(e,n){function t(){this.stack=[],this.popIdx=0}function r(e,n){this.node=e,this.body=n}n.exports=t,t.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new r(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],19:[function(e,n){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],20:[function(e,n){n.exports=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],21:[function(e,n){function t(e,n){function t(){return o(e,n,arguments)}return n=n||"Argument",{has:t}}function r(){function e(e,t){return o(e,t,n)}var n=arguments;return e}function o(e,n,t){if(void 0===e)throw new Error(n+" is not defined");for(var r=0;re)throw new Error("Invalid number of nodes");var n,t=l();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function r(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=t(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function o(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=l();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function i(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=l();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function a(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=l();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function s(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=l();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function u(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=l();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var s=i*e*n,u=r+o*e+s;r>0&&a.addLink(u,r-1+o*e+s),o>0&&a.addLink(u,r+(o-1)*e+s),i>0&&a.addLink(u,r+o*e+(i-1)*e*n)}return a}function f(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=l(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function c(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=l();for(n=0;e>n;++n)t.addNode(n);return t}function d(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,s=e("ngraph.random").random(o||42),u=l();for(i=0;n>i;++i)u.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,u.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(s.nextDouble()n)return!1;S(),P.splice(n,1);var t=u(e.fromId),o=u(e.toId);return t&&(n=r(e,t.links),n>=0&&t.links.splice(n,1)),o&&(n=r(e,o.links),n>=0&&o.links.splice(n,1)),T(e,"remove"),D(),!0}function p(e,n){var t,r=u(e);if(!r)return null;for(t=0;tn;++n)e(P[n])}function h(e,n,t){var r,o,i,a=u(e);if(a&&a.links&&"function"==typeof n)if(t)for(r=0;r0&&(M.fire("changed",I),I.length=0)}function w(){return Object.keys?b:E}function b(e){if("function"==typeof e)for(var n=Object.keys(L),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function o(e){this.id=e,this.links=[],this.data=null}function i(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=t;var a=e("ngraph.events")},{"ngraph.events":6}],25:[function(e,n){function t(e,n){var r;if(e||(e={}),n)for(r in n)if(n.hasOwnProperty(r)){var o=e.hasOwnProperty(r),i=typeof n[r],a=!o||typeof e[r]!==i;a?e[r]=n[r]:"object"===i&&(e[r]=t(e[r],n[r]))}return e}n.exports=t},{}],26:[function(e,n){function t(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function r(e,n){var r=n||t();if("function"!=typeof r.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var t,o,i;for(t=e.length-1;t>0;--t)o=r.next(t+1),i=e[o],e[o]=e[t],e[t]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,t,o;for(n=e.length-1;n>0;--n)t=r.next(n+1),o=e[t],e[t]=e[n],e[n]=o;return e}}}n.exports={random:t,randomIterator:r}},{}],27:[function(e,n){function t(e,n,t){function r(e){s.nodes.push(u(e))}function o(e){s.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var s={nodes:[],links:[]},u=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(s)}n.exports=t},{}],28:[function(e,n){function t(e,n){var t=r(e);if(void 0===n)return t;for(var o=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),s(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},k=function(e){p=!1,r.off("touchmove",A),r.off("touchend",k),r.off("touchcancel",k),c=null,a&&a(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,r.on("touchmove",A),r.on("touchend",k),r.on("touchcancel",k))},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return a=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),r.off("mousemove",w),r.off("mouseup",E),r.off("touchmove",A),r.off("touchend",k),r.off("touchcancel",k),P(null) +}}}n.exports=t;var r=e("../Utils/documentEvents.js"),o=e("../Utils/browserInfo.js"),i=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":40,"../Utils/documentEvents.js":41,"../Utils/findElementPosition.js":42}],37:[function(e,n){function t(e,n){var t=r(n),o=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){o=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(o);var r=i[e.id];return r&&r.onStart&&r.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(o),o=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(o){var t=i[o.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=t;var r=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":58}],38:[function(e,n){function t(e,n){function t(e){return d[e]}n=r(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var a=o(n.seed),s=new i(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),u={},f=function(){return{x:a.next(n.maxX),y:a.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],s)},p=function(){0!==e.getNodesCount()&&(s.x1=Number.MAX_VALUE,s.y1=Number.MAX_VALUE,s.x2=Number.MIN_VALUE,s.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){u[e.id]=e},g=function(e){for(var n=0;n0)for(e=0;en,t)}),e.forEachNode(O),H(),e.on("changed",q)},K=function(){y=!1,H(),W(),a.off("resize",V),j.removeAllListeners(),l.stop(),e.forEachLink(function(e){n.renderLinks&&B(e)}),e.forEachNode(function(e){F(e),U(e)}),v.dispose(),z()};return{run:function(e){return y||(k(),S(),D(),G(),$(),y=!0),T(e),this},reset:function(){g.resetScale(),D(),A.scale=1},pause:function(){P=!0,l.stop()},resume:function(){P=!1,l.restart()},rerender:function(){return _(),this},zoomOut:function(){return J(!0)},zoomIn:function(){return J(!1)},moveTo:function(e,n){g.graphCenterChanged(A.offsetX-e*A.scale,A.offsetY-n*A.scale),_()},getGraphics:function(){return g},dispose:function(){K()},on:function(e,n){return j.addEventListener(e,n),this},off:function(e,n){return j.removeEventListener(e,n),this}}}n.exports=t;var r=e("ngraph.graph"),o=e("ngraph.forcelayout"),i=e("./svgGraphics.js"),a=e("../Utils/windowEvents.js"),s=e("../Input/domInputManager.js"),u=e("../Utils/timer.js"),f=e("../Utils/getDimensions.js"),c=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.forcelayout":7,"ngraph.graph":24}],50:[function(e,n){function t(){function e(){var e=r("svg");return n=r("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,a,s,u,f=1,c={},d={},l=function(){return r("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(){return r("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+a+","+s+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){a=e,s=n,w()},inputManager:i,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var s="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",s)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),u=n.getCTM().multiply(i);f=u.a,a=u.e,s=u.f;var c="matrix("+u.a+", 0, 0,"+u.d+","+u.e+","+u.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof u&&u(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):u=e),t},getSvgRoot:function(){return t}};return o(b),b}n.exports=t;var r=e("simplesvg"),o=e("ngraph.events"),i=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":35,"ngraph.events":6,simplesvg:28}],51:[function(e,n){function t(e){e=f(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,c,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=o(),P=i(),N=function(){return a()},A=function(){return s(3014898687)},k=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),c&&c.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(A=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:r,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,k()},addLink:function(e,n){var t=m++,r=A(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],k()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,k(),I(this),y[0]},resetScale:function(){return j(),c&&(_(),k()),this},init:function(r){var o={};if(e.preserveDrawingBuffer&&(o.preserveDrawingBuffer=!0),n=r,_(),j(),n.appendChild(t),c=t.getContext("experimental-webgl",o),!c){var i="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(i),i}if(e.enableBlending&&(c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA),c.enable(c.BLEND)),e.clearColor){var a=e.clearColorValue;c.clearColor(a.r,a.g,a.b,a.a),this.beginRender=function(){c.clear(c.COLOR_BUFFER_BIT)}}L.load(c),L.updateSize(d/2,l/2),P.load(c),P.updateSize(d/2,l/2),k(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!c&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!c&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return u(T),T}n.exports=t;var r=e("../Input/webglInputManager.js"),o=e("../WebGL/webglLinkProgram.js"),i=e("../WebGL/webglNodeProgram.js"),a=e("../WebGL/webglSquare.js"),s=e("../WebGL/webglLine.js"),u=e("ngraph.events"),f=e("ngraph.merge")},{"../Input/webglInputManager.js":37,"../WebGL/webglLine.js":59,"../WebGL/webglLinkProgram.js":60,"../WebGL/webglNodeProgram.js":61,"../WebGL/webglSquare.js":62,"ngraph.events":6,"ngraph.merge":25}],52:[function(e,n){function t(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=t},{}],53:[function(e,n){function t(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=t},{}],54:[function(e,n){function t(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var s=e.getShaderInfoLog(o);throw window.alert(s),s}return o}function i(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function o(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=t},{}],55:[function(e,n){function t(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&u();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!r(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:i,getCoordinates:a,load:s};return E}function r(e){return 0===(e&e-1)}var o=e("./texture.js");n.exports=t},{"./texture.js":53}],56:[function(e,n){function t(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=t},{}],57:[function(e,n){function t(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=r(),A=o(),k=1024,j=0,_=new Float32Array(64);return{load:t,position:s,createNode:u,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function r(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function o(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var i=e("./webglAtlas.js"),a=e("./webgl.js");n.exports=t},{"./webgl.js":54,"./webglAtlas.js":55}],58:[function(e,n){function t(e){function n(){x=null}function t(e){x=e}function o(e){return"function"==typeof e&&A.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function s(e){return"function"==typeof e&&L.push(e),j}function u(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(A,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],A=[],k=e.getGraphicsRoot();h(k);var j={mouseEnter:c,mouseLeave:f,mouseDown:u,mouseUp:s,mouseMove:a,click:i,dblClick:o,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var r=e("../Utils/documentEvents.js");n.exports=t},{"../Utils/documentEvents.js":41}],59:[function(e,n){function t(e){return{color:r(e)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],60:[function(e,n){function t(){var e,n,t,o,i,a,s,u,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,o=r(a),e=o.createProgram(v,p),n.useProgram(e),i=o.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&o.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){s=e,u=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,s,u)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&o.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],61:[function(e,n){function t(){function e(){if((A+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=r(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function o(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){A>0&&(A-=1),e.id0&&v.copyArrayPart(N,e.id*x,A*x,x)}function s(){e(),A+=1}function u(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,A)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),A=0;return{load:n,position:t,updateTransform:o,updateSize:i,removeNode:a,createNode:s,replaceProperties:u,render:f}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],62:[function(e,n){function t(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],63:[function(e,n){n.exports="0.7.3"},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/package.json b/package.json index bb75a39..8ed0899 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,6 @@ "ngraph.merge": "0.0.1", "ngraph.random": "0.0.1", "ngraph.tojson": "0.1.1", - "simplesvg": "0.0.9" + "simplesvg": "0.0.10" } } diff --git a/src/version.js b/src/version.js index a85f616..4a32f39 100644 --- a/src/version.js +++ b/src/version.js @@ -1 +1 @@ -module.exports = '0.7.2'; +module.exports = '0.7.3'; From e735b35b803be7f52a5000f15298caf58a58d97a Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 22 Feb 2015 13:34:46 -0800 Subject: [PATCH 168/276] 0.7.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8ed0899..9b56a51 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.7.2", + "version": "0.7.3", "description": "Graph Drawing Library", "main": "dist/vivagraph", "directories": { From 72f7c86ec688357f36cbed4aa4ba7d5ac5d895f3 Mon Sep 17 00:00:00 2001 From: anvaka Date: Tue, 24 Feb 2015 19:52:55 -0800 Subject: [PATCH 169/276] Quadtree is now 1.6x faster See https://github.com/anvaka/ngraph.quadtreebh/commit/d9ec51e848acce22d63733fecdd0947161511c76 --- dist/vivagraph.js | 58 +++++++++++++++++++++++++++---------------- dist/vivagraph.min.js | 4 +-- package.json | 2 +- src/version.js | 2 +- 4 files changed, 41 insertions(+), 25 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 31ad651..aa4781a 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -1421,10 +1421,10 @@ module.exports = function(options) { // To avoid pressure on GC we reuse nodes. var node = nodesCache[currentInCache]; if (node) { - node.quads[0] = null; - node.quads[1] = null; - node.quads[2] = null; - node.quads[3] = null; + node.quad0 = null; + node.quad1 = null; + node.quad2 = null; + node.quad3 = null; node.body = null; node.mass = node.massX = node.massY = 0; node.left = node.right = node.top = node.bottom = 0; @@ -1478,7 +1478,7 @@ module.exports = function(options) { bottom = bottom + (bottom - oldTop); } - var child = node.quads[quadIdx]; + var child = getChild(node, quadIdx); if (!child) { // The node is internal but this quadrant is not taken. Add // subnode to it. @@ -1489,7 +1489,7 @@ module.exports = function(options) { child.bottom = bottom; child.body = body; - node.quads[quadIdx] = child; + setChild(node, quadIdx, child); } else { // continue searching in this quadrant. insertStack.push(child, body); @@ -1550,10 +1550,8 @@ module.exports = function(options) { queueLength -= 1; shiftIdx += 1; - // technically there should be external "if (body !== sourceBody) {" - // but in practice it gives slightghly worse performance, and does not - // have impact on layout correctness - if (body && body !== sourceBody) { + var differentBody = (body !== sourceBody); + if (body && differentBody) { // If the current node is a leaf node (and it is not source body), // calculate the force exerted by the current node on body, and add this // amount to body's net force. @@ -1573,7 +1571,7 @@ module.exports = function(options) { v = gravity * body.mass * sourceBody.mass / (r * r * r); fx += v * dx; fy += v * dy; - } else { + } else if (differentBody) { // Otherwise, calculate the ratio s / r, where s is the width of the region // represented by the internal node, and r is the distance between the body // and the node's center-of-mass @@ -1601,23 +1599,23 @@ module.exports = function(options) { // Otherwise, run the procedure recursively on each of the current node's children. // I intentionally unfolded this loop, to save several CPU cycles. - if (node.quads[0]) { - queue[pushIdx] = node.quads[0]; + if (node.quad0) { + queue[pushIdx] = node.quad0; queueLength += 1; pushIdx += 1; } - if (node.quads[1]) { - queue[pushIdx] = node.quads[1]; + if (node.quad1) { + queue[pushIdx] = node.quad1; queueLength += 1; pushIdx += 1; } - if (node.quads[2]) { - queue[pushIdx] = node.quads[2]; + if (node.quad2) { + queue[pushIdx] = node.quad2; queueLength += 1; pushIdx += 1; } - if (node.quads[3]) { - queue[pushIdx] = node.quads[3]; + if (node.quad3) { + queue[pushIdx] = node.quad3; queueLength += 1; pushIdx += 1; } @@ -1704,6 +1702,21 @@ module.exports = function(options) { }; }; +function getChild(node, idx) { + if (idx === 0) return node.quad0; + if (idx === 1) return node.quad1; + if (idx === 2) return node.quad2; + if (idx === 3) return node.quad3; + return null; +} + +function setChild(node, idx, child) { + if (idx === 0) node.quad0 = child; + else if (idx === 1) node.quad1 = child; + else if (idx === 2) node.quad2 = child; + else if (idx === 3) node.quad3 = child; +} + },{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":26}],18:[function(require,module,exports){ module.exports = InsertStack; @@ -1769,7 +1782,10 @@ module.exports = function Node() { // 0 | 1 // ----- // 2 | 3 - this.quads = []; + this.quad0 = null; + this.quad1 = null; + this.quad2 = null; + this.quad3 = null; // Total mass of current node this.mass = 0; @@ -6783,7 +6799,7 @@ function webglSquare(size, color) { } },{"./parseColor.js":52}],63:[function(require,module,exports){ -module.exports = '0.7.3'; +module.exports = '0.7.4'; },{}]},{},[1])(1) }); \ No newline at end of file diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 18060e0..d2657a4 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,s){if(!t[a]){if(!n[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=s-i,d=o-a,p=a*i-o*s,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=u*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-u*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=t},{}],3:[function(e,n){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n){function t(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){u=e.id,s(u),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function g(e){var n=w[e];n.mass=y(e)}function h(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function m(e){var n=w[e];return n||(c(e),n=w[e]),n}function y(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var x=e("ngraph.physics.simulator");t=t||x(),o(t,"physicsSimulator").has("step","getBestNewBodyPosition","addBodyAt");var w="function"==typeof Object.create?Object.create(null):{},b={},E=t.settings.springTransform||r;f(),s();var L={step:function(){return t.step()},getNodePosition:function(e){return m(e).pos},setNodePosition:function(e){var n=m(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return t.getBBox()},pinNode:function(e,n){var t=m(e.id);t.isPinned=!!n},isNodePinned:function(e){return m(e.id).isPinned},dispose:function(){n.off("changed",u)},getBody:a,getSpring:i,simulator:t};return L}function r(){}n.exports=t,n.exports.simulator=e("ngraph.physics.simulator");var o=e("varta")},{"ngraph.physics.simulator":8,varta:21}],8:[function(e,n){function t(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.force.reset(),v.updateBodyForce(e),m.update(e);for(n=p.length;n--;)h.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),s=n.createBounds||e("./lib/bounds"),u=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),g=s(l,n),h=f(n),m=u(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return g.update(),en))return l.splice(n,1),0===l.length&&g.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return g.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=t},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":25,"ngraph.quadtreebh":17}],9:[function(e,n){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var s=n[e];s.isPinned?(s.pos.x=s.prevPos.x,s.pos.y=s.prevPos.y):(s.prevPos.x=s.pos.x,s.prevPos.y=s.pos.y),s.pos.xo&&(o=s.pos.x),s.pos.ya&&(a=s.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var s=0;st;++t){var u=e[t],f=n/u.mass;u.velocity.x+=f*u.force.x,u.velocity.y+=f*u.force.y;var c=u.velocity.x,d=u.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(u.velocity.x=c/l,u.velocity.y=d/l),r=n*u.velocity.x,i=n*u.velocity.y,u.pos.x+=r,u.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=t},{}],13:[function(e,n){function t(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=t},{}],14:[function(e,n){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,s=o.pos.y-t.pos.y,u=Math.sqrt(a*a+s*s);0===u&&(a=(r.nextDouble()-.5)/50,s=(r.nextDouble()-.5)/50,u=Math.sqrt(a*a+s*s));var f=u-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/u*e.weight;t.force.x+=c*a,t.force.y+=c*s,o.force.x-=c*a,o.force.y-=c*s}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":25,"ngraph.random":26}],15:[function(e,n){function t(e,n,t){var o="[object Array]"===Object.prototype.toString.call(t);if(o)for(var i=0;i0&&i(a.pos,o.pos));if(0===s&&i(a.pos,o.pos))return}u.push(r,a),u.push(r,o)}else{var v=o.pos.x,g=o.pos.y;r.mass=r.mass+o.mass,r.massX=r.massX+o.mass*v,r.massY=r.massY+o.mass*g;var h=0,m=r.left,y=(r.right+m)/2,x=r.top,w=(r.bottom+x)/2;if(v>y){h+=1;var b=m;m=y,y+=y-b}if(g>w){h+=2;var E=x;x=w,w+=w-E}var L=r.quads[h];L?u.push(L,o):(L=l(),L.left=m,L.top=x,L.right=y,L.bottom=w,L.body=o,r.quads[h]=L)}}},g=function(e){var n,r,o,i,u=s,c=0,d=0,l=1,v=0,g=1;for(u[0]=p;l;){var h=u[v],m=h.body;l-=1,v+=1,m&&m!==e?(r=m.pos.x-e.pos.x,o=m.pos.y-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),n=a*m.mass*e.mass/(i*i*i),c+=n*r,d+=n*o):(r=h.massX/h.mass-e.pos.x,o=h.massY/h.mass-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),(h.right-h.left)/is&&(t=s),s>o&&(o=s),r>u&&(r=u),u>i&&(i=u)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,d=0,p=l(),p.left=t,p.right=o,p.top=r,p.bottom=i,n=a-1,n>0&&(p.body=e[n]);n--;)v(e[n],p)};return{insertBodies:h,updateBodyForce:g,options:function(e){return e?("number"==typeof e.gravity&&(a=e.gravity),"number"==typeof e.theta&&(f=e.theta),this):{gravity:a,theta:f}}}}},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":26}],18:[function(e,n){function t(){this.stack=[],this.popIdx=0}function r(e,n){this.node=e,this.body=n}n.exports=t,t.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new r(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],19:[function(e,n){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],20:[function(e,n){n.exports=function(){this.body=null,this.quads=[],this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],21:[function(e,n){function t(e,n){function t(){return o(e,n,arguments)}return n=n||"Argument",{has:t}}function r(){function e(e,t){return o(e,t,n)}var n=arguments;return e}function o(e,n,t){if(void 0===e)throw new Error(n+" is not defined");for(var r=0;re)throw new Error("Invalid number of nodes");var n,t=l();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function r(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=t(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function o(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=l();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function i(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=l();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function a(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=l();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function s(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=l();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function u(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=l();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var s=i*e*n,u=r+o*e+s;r>0&&a.addLink(u,r-1+o*e+s),o>0&&a.addLink(u,r+(o-1)*e+s),i>0&&a.addLink(u,r+o*e+(i-1)*e*n)}return a}function f(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=l(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function c(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=l();for(n=0;e>n;++n)t.addNode(n);return t}function d(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,s=e("ngraph.random").random(o||42),u=l();for(i=0;n>i;++i)u.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,u.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(s.nextDouble()n)return!1;S(),P.splice(n,1);var t=u(e.fromId),o=u(e.toId);return t&&(n=r(e,t.links),n>=0&&t.links.splice(n,1)),o&&(n=r(e,o.links),n>=0&&o.links.splice(n,1)),T(e,"remove"),D(),!0}function p(e,n){var t,r=u(e);if(!r)return null;for(t=0;tn;++n)e(P[n])}function h(e,n,t){var r,o,i,a=u(e);if(a&&a.links&&"function"==typeof n)if(t)for(r=0;r0&&(M.fire("changed",I),I.length=0)}function w(){return Object.keys?b:E}function b(e){if("function"==typeof e)for(var n=Object.keys(L),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function o(e){this.id=e,this.links=[],this.data=null}function i(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=t;var a=e("ngraph.events")},{"ngraph.events":6}],25:[function(e,n){function t(e,n){var r;if(e||(e={}),n)for(r in n)if(n.hasOwnProperty(r)){var o=e.hasOwnProperty(r),i=typeof n[r],a=!o||typeof e[r]!==i;a?e[r]=n[r]:"object"===i&&(e[r]=t(e[r],n[r]))}return e}n.exports=t},{}],26:[function(e,n){function t(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function r(e,n){var r=n||t();if("function"!=typeof r.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var t,o,i;for(t=e.length-1;t>0;--t)o=r.next(t+1),i=e[o],e[o]=e[t],e[t]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,t,o;for(n=e.length-1;n>0;--n)t=r.next(n+1),o=e[t],e[t]=e[n],e[n]=o;return e}}}n.exports={random:t,randomIterator:r}},{}],27:[function(e,n){function t(e,n,t){function r(e){s.nodes.push(u(e))}function o(e){s.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var s={nodes:[],links:[]},u=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(s)}n.exports=t},{}],28:[function(e,n){function t(e,n){var t=r(e);if(void 0===n)return t;for(var o=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),s(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},k=function(e){p=!1,r.off("touchmove",A),r.off("touchend",k),r.off("touchcancel",k),c=null,a&&a(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,r.on("touchmove",A),r.on("touchend",k),r.on("touchcancel",k))},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return a=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),r.off("mousemove",w),r.off("mouseup",E),r.off("touchmove",A),r.off("touchend",k),r.off("touchcancel",k),P(null) -}}}n.exports=t;var r=e("../Utils/documentEvents.js"),o=e("../Utils/browserInfo.js"),i=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":40,"../Utils/documentEvents.js":41,"../Utils/findElementPosition.js":42}],37:[function(e,n){function t(e,n){var t=r(n),o=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){o=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(o);var r=i[e.id];return r&&r.onStart&&r.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(o),o=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(o){var t=i[o.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=t;var r=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":58}],38:[function(e,n){function t(e,n){function t(e){return d[e]}n=r(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var a=o(n.seed),s=new i(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),u={},f=function(){return{x:a.next(n.maxX),y:a.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],s)},p=function(){0!==e.getNodesCount()&&(s.x1=Number.MAX_VALUE,s.y1=Number.MAX_VALUE,s.x2=Number.MIN_VALUE,s.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){u[e.id]=e},g=function(e){for(var n=0;n0)for(e=0;en,t)}),e.forEachNode(O),H(),e.on("changed",q)},K=function(){y=!1,H(),W(),a.off("resize",V),j.removeAllListeners(),l.stop(),e.forEachLink(function(e){n.renderLinks&&B(e)}),e.forEachNode(function(e){F(e),U(e)}),v.dispose(),z()};return{run:function(e){return y||(k(),S(),D(),G(),$(),y=!0),T(e),this},reset:function(){g.resetScale(),D(),A.scale=1},pause:function(){P=!0,l.stop()},resume:function(){P=!1,l.restart()},rerender:function(){return _(),this},zoomOut:function(){return J(!0)},zoomIn:function(){return J(!1)},moveTo:function(e,n){g.graphCenterChanged(A.offsetX-e*A.scale,A.offsetY-n*A.scale),_()},getGraphics:function(){return g},dispose:function(){K()},on:function(e,n){return j.addEventListener(e,n),this},off:function(e,n){return j.removeEventListener(e,n),this}}}n.exports=t;var r=e("ngraph.graph"),o=e("ngraph.forcelayout"),i=e("./svgGraphics.js"),a=e("../Utils/windowEvents.js"),s=e("../Input/domInputManager.js"),u=e("../Utils/timer.js"),f=e("../Utils/getDimensions.js"),c=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.forcelayout":7,"ngraph.graph":24}],50:[function(e,n){function t(){function e(){var e=r("svg");return n=r("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,a,s,u,f=1,c={},d={},l=function(){return r("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(){return r("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+a+","+s+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){a=e,s=n,w()},inputManager:i,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var s="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",s)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),u=n.getCTM().multiply(i);f=u.a,a=u.e,s=u.f;var c="matrix("+u.a+", 0, 0,"+u.d+","+u.e+","+u.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof u&&u(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):u=e),t},getSvgRoot:function(){return t}};return o(b),b}n.exports=t;var r=e("simplesvg"),o=e("ngraph.events"),i=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":35,"ngraph.events":6,simplesvg:28}],51:[function(e,n){function t(e){e=f(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,c,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=o(),P=i(),N=function(){return a()},A=function(){return s(3014898687)},k=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),c&&c.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(A=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:r,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,k()},addLink:function(e,n){var t=m++,r=A(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],k()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,k(),I(this),y[0]},resetScale:function(){return j(),c&&(_(),k()),this},init:function(r){var o={};if(e.preserveDrawingBuffer&&(o.preserveDrawingBuffer=!0),n=r,_(),j(),n.appendChild(t),c=t.getContext("experimental-webgl",o),!c){var i="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(i),i}if(e.enableBlending&&(c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA),c.enable(c.BLEND)),e.clearColor){var a=e.clearColorValue;c.clearColor(a.r,a.g,a.b,a.a),this.beginRender=function(){c.clear(c.COLOR_BUFFER_BIT)}}L.load(c),L.updateSize(d/2,l/2),P.load(c),P.updateSize(d/2,l/2),k(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!c&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!c&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return u(T),T}n.exports=t;var r=e("../Input/webglInputManager.js"),o=e("../WebGL/webglLinkProgram.js"),i=e("../WebGL/webglNodeProgram.js"),a=e("../WebGL/webglSquare.js"),s=e("../WebGL/webglLine.js"),u=e("ngraph.events"),f=e("ngraph.merge")},{"../Input/webglInputManager.js":37,"../WebGL/webglLine.js":59,"../WebGL/webglLinkProgram.js":60,"../WebGL/webglNodeProgram.js":61,"../WebGL/webglSquare.js":62,"ngraph.events":6,"ngraph.merge":25}],52:[function(e,n){function t(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=t},{}],53:[function(e,n){function t(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=t},{}],54:[function(e,n){function t(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var s=e.getShaderInfoLog(o);throw window.alert(s),s}return o}function i(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function o(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=t},{}],55:[function(e,n){function t(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&u();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!r(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:i,getCoordinates:a,load:s};return E}function r(e){return 0===(e&e-1)}var o=e("./texture.js");n.exports=t},{"./texture.js":53}],56:[function(e,n){function t(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=t},{}],57:[function(e,n){function t(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=r(),A=o(),k=1024,j=0,_=new Float32Array(64);return{load:t,position:s,createNode:u,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function r(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function o(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var i=e("./webglAtlas.js"),a=e("./webgl.js");n.exports=t},{"./webgl.js":54,"./webglAtlas.js":55}],58:[function(e,n){function t(e){function n(){x=null}function t(e){x=e}function o(e){return"function"==typeof e&&A.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function s(e){return"function"==typeof e&&L.push(e),j}function u(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(A,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],A=[],k=e.getGraphicsRoot();h(k);var j={mouseEnter:c,mouseLeave:f,mouseDown:u,mouseUp:s,mouseMove:a,click:i,dblClick:o,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var r=e("../Utils/documentEvents.js");n.exports=t},{"../Utils/documentEvents.js":41}],59:[function(e,n){function t(e){return{color:r(e)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],60:[function(e,n){function t(){var e,n,t,o,i,a,s,u,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,o=r(a),e=o.createProgram(v,p),n.useProgram(e),i=o.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&o.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){s=e,u=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,s,u)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&o.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],61:[function(e,n){function t(){function e(){if((A+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=r(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function o(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){A>0&&(A-=1),e.id0&&v.copyArrayPart(N,e.id*x,A*x,x)}function s(){e(),A+=1}function u(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,A)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),A=0;return{load:n,position:t,updateTransform:o,updateSize:i,removeNode:a,createNode:s,replaceProperties:u,render:f}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],62:[function(e,n){function t(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],63:[function(e,n){n.exports="0.7.3"},{}]},{},[1])(1)}); \ No newline at end of file +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-s*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=t},{}],3:[function(e,n){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n){function t(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function g(e){var n=w[e];n.mass=y(e)}function h(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function m(e){var n=w[e];return n||(c(e),n=w[e]),n}function y(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var x=e("ngraph.physics.simulator");t=t||x(),o(t,"physicsSimulator").has("step","getBestNewBodyPosition","addBodyAt");var w="function"==typeof Object.create?Object.create(null):{},b={},E=t.settings.springTransform||r;f(),u();var L={step:function(){return t.step()},getNodePosition:function(e){return m(e).pos},setNodePosition:function(e){var n=m(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return t.getBBox()},pinNode:function(e,n){var t=m(e.id);t.isPinned=!!n},isNodePinned:function(e){return m(e.id).isPinned},dispose:function(){n.off("changed",s)},getBody:a,getSpring:i,simulator:t};return L}function r(){}n.exports=t,n.exports.simulator=e("ngraph.physics.simulator");var o=e("varta")},{"ngraph.physics.simulator":8,varta:21}],8:[function(e,n){function t(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.force.reset(),v.updateBodyForce(e),m.update(e);for(n=p.length;n--;)h.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),u=n.createBounds||e("./lib/bounds"),s=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),g=u(l,n),h=f(n),m=s(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return g.update(),en))return l.splice(n,1),0===l.length&&g.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return g.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=t},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":25,"ngraph.quadtreebh":17}],9:[function(e,n){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;ut;++t){var s=e[t],f=n/s.mass;s.velocity.x+=f*s.force.x,s.velocity.y+=f*s.force.y;var c=s.velocity.x,d=s.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=t},{}],13:[function(e,n){function t(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=t},{}],14:[function(e,n){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":25,"ngraph.random":26}],15:[function(e,n){function t(e,n,t){var o="[object Array]"===Object.prototype.toString.call(t);if(o)for(var i=0;i0&&u(s.pos,a.pos));if(0===f&&u(s.pos,a.pos))return}c.push(i,s),c.push(i,a)}else{var h=a.pos.x,m=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*h,i.massY=i.massY+a.mass*m;var y=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;if(h>w){y+=1;var L=x;x=w,w+=w-L}if(m>E){y+=2;var P=b;b=E,E+=E-P}var N=t(i,y);N?c.push(N,a):(N=v(),N.left=x,N.top=b,N.right=w,N.bottom=E,N.body=a,r(i,y,N))}}},m=function(e){var n,t,r,i,a=f,u=0,c=0,l=1,p=0,v=1;for(a[0]=g;l;){var h=a[p],m=h.body;l-=1,p+=1;var y=m!==e;m&&y?(t=m.pos.x-e.pos.x,r=m.pos.y-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),n=s*m.mass*e.mass/(i*i*i),u+=n*t,c+=n*r):y&&(t=h.massX/h.mass-e.pos.x,r=h.massY/h.mass-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),(h.right-h.left)/iu&&(t=u),u>o&&(o=u),r>s&&(r=s),s>i&&(i=s)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,p=0,g=v(),g.left=t,g.right=o,g.top=r,g.bottom=i,n=a-1,n>0&&(g.body=e[n]);n--;)h(e[n],g)};return{insertBodies:y,updateBodyForce:m,options:function(e){return e?("number"==typeof e.gravity&&(s=e.gravity),"number"==typeof e.theta&&(d=e.theta),this):{gravity:s,theta:d}}}}},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":26}],18:[function(e,n){function t(){this.stack=[],this.popIdx=0}function r(e,n){this.node=e,this.body=n}n.exports=t,t.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new r(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],19:[function(e,n){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],20:[function(e,n){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],21:[function(e,n){function t(e,n){function t(){return o(e,n,arguments)}return n=n||"Argument",{has:t}}function r(){function e(e,t){return o(e,t,n)}var n=arguments;return e}function o(e,n,t){if(void 0===e)throw new Error(n+" is not defined");for(var r=0;re)throw new Error("Invalid number of nodes");var n,t=l();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function r(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=t(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function o(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=l();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function i(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=l();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function a(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=l();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function u(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=l();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function s(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=l();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var u=i*e*n,s=r+o*e+u;r>0&&a.addLink(s,r-1+o*e+u),o>0&&a.addLink(s,r+(o-1)*e+u),i>0&&a.addLink(s,r+o*e+(i-1)*e*n)}return a}function f(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=l(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function c(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=l();for(n=0;e>n;++n)t.addNode(n);return t}function d(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,u=e("ngraph.random").random(o||42),s=l();for(i=0;n>i;++i)s.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,s.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(u.nextDouble()n)return!1;S(),P.splice(n,1);var t=s(e.fromId),o=s(e.toId);return t&&(n=r(e,t.links),n>=0&&t.links.splice(n,1)),o&&(n=r(e,o.links),n>=0&&o.links.splice(n,1)),T(e,"remove"),D(),!0}function p(e,n){var t,r=s(e);if(!r)return null;for(t=0;tn;++n)e(P[n])}function h(e,n,t){var r,o,i,a=s(e);if(a&&a.links&&"function"==typeof n)if(t)for(r=0;r0&&(M.fire("changed",I),I.length=0)}function w(){return Object.keys?b:E}function b(e){if("function"==typeof e)for(var n=Object.keys(L),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function o(e){this.id=e,this.links=[],this.data=null}function i(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=t;var a=e("ngraph.events")},{"ngraph.events":6}],25:[function(e,n){function t(e,n){var r;if(e||(e={}),n)for(r in n)if(n.hasOwnProperty(r)){var o=e.hasOwnProperty(r),i=typeof n[r],a=!o||typeof e[r]!==i;a?e[r]=n[r]:"object"===i&&(e[r]=t(e[r],n[r]))}return e}n.exports=t},{}],26:[function(e,n){function t(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function r(e,n){var r=n||t();if("function"!=typeof r.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var t,o,i;for(t=e.length-1;t>0;--t)o=r.next(t+1),i=e[o],e[o]=e[t],e[t]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,t,o;for(n=e.length-1;n>0;--n)t=r.next(n+1),o=e[t],e[t]=e[n],e[n]=o;return e}}}n.exports={random:t,randomIterator:r}},{}],27:[function(e,n){function t(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=t},{}],28:[function(e,n){function t(e,n){var t=r(e);if(void 0===n)return t;for(var o=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},k=function(e){p=!1,r.off("touchmove",A),r.off("touchend",k),r.off("touchcancel",k),c=null,a&&a(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,r.on("touchmove",A),r.on("touchend",k),r.on("touchcancel",k))},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this +},onStop:function(e){return a=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),r.off("mousemove",w),r.off("mouseup",E),r.off("touchmove",A),r.off("touchend",k),r.off("touchcancel",k),P(null)}}}n.exports=t;var r=e("../Utils/documentEvents.js"),o=e("../Utils/browserInfo.js"),i=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":40,"../Utils/documentEvents.js":41,"../Utils/findElementPosition.js":42}],37:[function(e,n){function t(e,n){var t=r(n),o=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){o=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(o);var r=i[e.id];return r&&r.onStart&&r.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(o),o=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(o){var t=i[o.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=t;var r=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":58}],38:[function(e,n){function t(e,n){function t(e){return d[e]}n=r(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var a=o(n.seed),u=new i(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(){return{x:a.next(n.maxX),y:a.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n0)for(e=0;en,t)}),e.forEachNode(O),H(),e.on("changed",X)},K=function(){y=!1,H(),W(),a.off("resize",V),j.removeAllListeners(),l.stop(),e.forEachLink(function(e){n.renderLinks&&B(e)}),e.forEachNode(function(e){F(e),U(e)}),v.dispose(),z()};return{run:function(e){return y||(k(),S(),D(),G(),$(),y=!0),T(e),this},reset:function(){g.resetScale(),D(),A.scale=1},pause:function(){P=!0,l.stop()},resume:function(){P=!1,l.restart()},rerender:function(){return _(),this},zoomOut:function(){return J(!0)},zoomIn:function(){return J(!1)},moveTo:function(e,n){g.graphCenterChanged(A.offsetX-e*A.scale,A.offsetY-n*A.scale),_()},getGraphics:function(){return g},dispose:function(){K()},on:function(e,n){return j.addEventListener(e,n),this},off:function(e,n){return j.removeEventListener(e,n),this}}}n.exports=t;var r=e("ngraph.graph"),o=e("ngraph.forcelayout"),i=e("./svgGraphics.js"),a=e("../Utils/windowEvents.js"),u=e("../Input/domInputManager.js"),s=e("../Utils/timer.js"),f=e("../Utils/getDimensions.js"),c=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.forcelayout":7,"ngraph.graph":24}],50:[function(e,n){function t(){function e(){var e=r("svg");return n=r("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,a,u,s,f=1,c={},d={},l=function(){return r("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(){return r("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+a+","+u+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){a=e,u=n,w()},inputManager:i,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),s=n.getCTM().multiply(i);f=s.a,a=s.e,u=s.f;var c="matrix("+s.a+", 0, 0,"+s.d+","+s.e+","+s.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof s&&s(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):s=e),t},getSvgRoot:function(){return t}};return o(b),b}n.exports=t;var r=e("simplesvg"),o=e("ngraph.events"),i=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":35,"ngraph.events":6,simplesvg:28}],51:[function(e,n){function t(e){e=f(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,c,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=o(),P=i(),N=function(){return a()},A=function(){return u(3014898687)},k=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),c&&c.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(A=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:r,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,k()},addLink:function(e,n){var t=m++,r=A(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],k()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,k(),I(this),y[0]},resetScale:function(){return j(),c&&(_(),k()),this},init:function(r){var o={};if(e.preserveDrawingBuffer&&(o.preserveDrawingBuffer=!0),n=r,_(),j(),n.appendChild(t),c=t.getContext("experimental-webgl",o),!c){var i="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(i),i}if(e.enableBlending&&(c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA),c.enable(c.BLEND)),e.clearColor){var a=e.clearColorValue;c.clearColor(a.r,a.g,a.b,a.a),this.beginRender=function(){c.clear(c.COLOR_BUFFER_BIT)}}L.load(c),L.updateSize(d/2,l/2),P.load(c),P.updateSize(d/2,l/2),k(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!c&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!c&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return s(T),T}n.exports=t;var r=e("../Input/webglInputManager.js"),o=e("../WebGL/webglLinkProgram.js"),i=e("../WebGL/webglNodeProgram.js"),a=e("../WebGL/webglSquare.js"),u=e("../WebGL/webglLine.js"),s=e("ngraph.events"),f=e("ngraph.merge")},{"../Input/webglInputManager.js":37,"../WebGL/webglLine.js":59,"../WebGL/webglLinkProgram.js":60,"../WebGL/webglNodeProgram.js":61,"../WebGL/webglSquare.js":62,"ngraph.events":6,"ngraph.merge":25}],52:[function(e,n){function t(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=t},{}],53:[function(e,n){function t(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=t},{}],54:[function(e,n){function t(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function i(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function o(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=t},{}],55:[function(e,n){function t(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!r(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:i,getCoordinates:a,load:u};return E}function r(e){return 0===(e&e-1)}var o=e("./texture.js");n.exports=t},{"./texture.js":53}],56:[function(e,n){function t(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=t},{}],57:[function(e,n){function t(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=r(),A=o(),k=1024,j=0,_=new Float32Array(64);return{load:t,position:u,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function r(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function o(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var i=e("./webglAtlas.js"),a=e("./webgl.js");n.exports=t},{"./webgl.js":54,"./webglAtlas.js":55}],58:[function(e,n){function t(e){function n(){x=null}function t(e){x=e}function o(e){return"function"==typeof e&&A.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(A,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],A=[],k=e.getGraphicsRoot();h(k);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:o,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var r=e("../Utils/documentEvents.js");n.exports=t},{"../Utils/documentEvents.js":41}],59:[function(e,n){function t(e){return{color:r(e)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],60:[function(e,n){function t(){var e,n,t,o,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,o=r(a),e=o.createProgram(v,p),n.useProgram(e),i=o.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&o.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&o.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],61:[function(e,n){function t(){function e(){if((A+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=r(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function o(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){A>0&&(A-=1),e.id0&&v.copyArrayPart(N,e.id*x,A*x,x)}function u(){e(),A+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,A)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),A=0;return{load:n,position:t,updateTransform:o,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],62:[function(e,n){function t(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],63:[function(e,n){n.exports="0.7.4"},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/package.json b/package.json index 9b56a51..edeb117 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "gintersect": "0.1.0", "ngraph.centrality": "0.1.1", "ngraph.events": "0.0.3", - "ngraph.forcelayout": "0.0.15", + "ngraph.forcelayout": "0.0.16", "ngraph.fromjson": "0.1.4", "ngraph.generators": "0.0.13", "ngraph.graph": "0.0.8", diff --git a/src/version.js b/src/version.js index 4a32f39..392a0a0 100644 --- a/src/version.js +++ b/src/version.js @@ -1 +1 @@ -module.exports = '0.7.3'; +module.exports = '0.7.4'; From 2eead99acafdfe149d6e5656bba912edd1ea4cdc Mon Sep 17 00:00:00 2001 From: anvaka Date: Tue, 24 Feb 2015 19:53:18 -0800 Subject: [PATCH 170/276] 0.7.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index edeb117..5dfd8a2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.7.3", + "version": "0.7.4", "description": "Graph Drawing Library", "main": "dist/vivagraph", "directories": { From 7565a5266334bf461e5ae780281774170a432dbe Mon Sep 17 00:00:00 2001 From: anvaka Date: Thu, 26 Feb 2015 18:16:58 -0800 Subject: [PATCH 171/276] Use src/viva in node Fixes https://github.com/anvaka/VivaGraphJS/issues/127 --- package.json | 2 +- src/version.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 5dfd8a2..8670a32 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "vivagraphjs", "version": "0.7.4", "description": "Graph Drawing Library", - "main": "dist/vivagraph", + "main": "src/viva", "directories": { "doc": "docs" }, diff --git a/src/version.js b/src/version.js index 392a0a0..d960c51 100644 --- a/src/version.js +++ b/src/version.js @@ -1 +1,2 @@ -module.exports = '0.7.4'; +// todo: this should be generated at build time. +module.exports = '0.7.5'; From e70083c8ea45a0bddeefbfda792d5850e354ccf4 Mon Sep 17 00:00:00 2001 From: anvaka Date: Thu, 26 Feb 2015 18:19:28 -0800 Subject: [PATCH 172/276] 0.7.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8670a32..ea5d121 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.7.4", + "version": "0.7.5", "description": "Graph Drawing Library", "main": "src/viva", "directories": { From a81a82758620d19f11433504986fdbfad1834921 Mon Sep 17 00:00:00 2001 From: anvaka Date: Fri, 27 Feb 2015 20:19:07 -0800 Subject: [PATCH 173/276] Removed unused code --- dist/vivagraph.js | 3 ++- dist/vivagraph.min.js | 2 +- gulpfile.js | 50 ------------------------------------------- 3 files changed, 3 insertions(+), 52 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index aa4781a..7ab881a 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -6799,7 +6799,8 @@ function webglSquare(size, color) { } },{"./parseColor.js":52}],63:[function(require,module,exports){ -module.exports = '0.7.4'; +// todo: this should be generated at build time. +module.exports = '0.7.5'; },{}]},{},[1])(1) }); \ No newline at end of file diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index d2657a4..52c834d 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-s*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=t},{}],3:[function(e,n){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n){function t(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function g(e){var n=w[e];n.mass=y(e)}function h(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function m(e){var n=w[e];return n||(c(e),n=w[e]),n}function y(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var x=e("ngraph.physics.simulator");t=t||x(),o(t,"physicsSimulator").has("step","getBestNewBodyPosition","addBodyAt");var w="function"==typeof Object.create?Object.create(null):{},b={},E=t.settings.springTransform||r;f(),u();var L={step:function(){return t.step()},getNodePosition:function(e){return m(e).pos},setNodePosition:function(e){var n=m(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return t.getBBox()},pinNode:function(e,n){var t=m(e.id);t.isPinned=!!n},isNodePinned:function(e){return m(e.id).isPinned},dispose:function(){n.off("changed",s)},getBody:a,getSpring:i,simulator:t};return L}function r(){}n.exports=t,n.exports.simulator=e("ngraph.physics.simulator");var o=e("varta")},{"ngraph.physics.simulator":8,varta:21}],8:[function(e,n){function t(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.force.reset(),v.updateBodyForce(e),m.update(e);for(n=p.length;n--;)h.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),u=n.createBounds||e("./lib/bounds"),s=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),g=u(l,n),h=f(n),m=s(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return g.update(),en))return l.splice(n,1),0===l.length&&g.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return g.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=t},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":25,"ngraph.quadtreebh":17}],9:[function(e,n){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;ut;++t){var s=e[t],f=n/s.mass;s.velocity.x+=f*s.force.x,s.velocity.y+=f*s.force.y;var c=s.velocity.x,d=s.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=t},{}],13:[function(e,n){function t(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=t},{}],14:[function(e,n){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":25,"ngraph.random":26}],15:[function(e,n){function t(e,n,t){var o="[object Array]"===Object.prototype.toString.call(t);if(o)for(var i=0;i0&&u(s.pos,a.pos));if(0===f&&u(s.pos,a.pos))return}c.push(i,s),c.push(i,a)}else{var h=a.pos.x,m=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*h,i.massY=i.massY+a.mass*m;var y=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;if(h>w){y+=1;var L=x;x=w,w+=w-L}if(m>E){y+=2;var P=b;b=E,E+=E-P}var N=t(i,y);N?c.push(N,a):(N=v(),N.left=x,N.top=b,N.right=w,N.bottom=E,N.body=a,r(i,y,N))}}},m=function(e){var n,t,r,i,a=f,u=0,c=0,l=1,p=0,v=1;for(a[0]=g;l;){var h=a[p],m=h.body;l-=1,p+=1;var y=m!==e;m&&y?(t=m.pos.x-e.pos.x,r=m.pos.y-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),n=s*m.mass*e.mass/(i*i*i),u+=n*t,c+=n*r):y&&(t=h.massX/h.mass-e.pos.x,r=h.massY/h.mass-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),(h.right-h.left)/iu&&(t=u),u>o&&(o=u),r>s&&(r=s),s>i&&(i=s)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,p=0,g=v(),g.left=t,g.right=o,g.top=r,g.bottom=i,n=a-1,n>0&&(g.body=e[n]);n--;)h(e[n],g)};return{insertBodies:y,updateBodyForce:m,options:function(e){return e?("number"==typeof e.gravity&&(s=e.gravity),"number"==typeof e.theta&&(d=e.theta),this):{gravity:s,theta:d}}}}},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":26}],18:[function(e,n){function t(){this.stack=[],this.popIdx=0}function r(e,n){this.node=e,this.body=n}n.exports=t,t.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new r(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],19:[function(e,n){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],20:[function(e,n){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],21:[function(e,n){function t(e,n){function t(){return o(e,n,arguments)}return n=n||"Argument",{has:t}}function r(){function e(e,t){return o(e,t,n)}var n=arguments;return e}function o(e,n,t){if(void 0===e)throw new Error(n+" is not defined");for(var r=0;re)throw new Error("Invalid number of nodes");var n,t=l();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function r(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=t(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function o(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=l();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function i(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=l();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function a(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=l();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function u(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=l();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function s(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=l();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var u=i*e*n,s=r+o*e+u;r>0&&a.addLink(s,r-1+o*e+u),o>0&&a.addLink(s,r+(o-1)*e+u),i>0&&a.addLink(s,r+o*e+(i-1)*e*n)}return a}function f(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=l(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function c(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=l();for(n=0;e>n;++n)t.addNode(n);return t}function d(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,u=e("ngraph.random").random(o||42),s=l();for(i=0;n>i;++i)s.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,s.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(u.nextDouble()n)return!1;S(),P.splice(n,1);var t=s(e.fromId),o=s(e.toId);return t&&(n=r(e,t.links),n>=0&&t.links.splice(n,1)),o&&(n=r(e,o.links),n>=0&&o.links.splice(n,1)),T(e,"remove"),D(),!0}function p(e,n){var t,r=s(e);if(!r)return null;for(t=0;tn;++n)e(P[n])}function h(e,n,t){var r,o,i,a=s(e);if(a&&a.links&&"function"==typeof n)if(t)for(r=0;r0&&(M.fire("changed",I),I.length=0)}function w(){return Object.keys?b:E}function b(e){if("function"==typeof e)for(var n=Object.keys(L),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function o(e){this.id=e,this.links=[],this.data=null}function i(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=t;var a=e("ngraph.events")},{"ngraph.events":6}],25:[function(e,n){function t(e,n){var r;if(e||(e={}),n)for(r in n)if(n.hasOwnProperty(r)){var o=e.hasOwnProperty(r),i=typeof n[r],a=!o||typeof e[r]!==i;a?e[r]=n[r]:"object"===i&&(e[r]=t(e[r],n[r]))}return e}n.exports=t},{}],26:[function(e,n){function t(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function r(e,n){var r=n||t();if("function"!=typeof r.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var t,o,i;for(t=e.length-1;t>0;--t)o=r.next(t+1),i=e[o],e[o]=e[t],e[t]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,t,o;for(n=e.length-1;n>0;--n)t=r.next(n+1),o=e[t],e[t]=e[n],e[n]=o;return e}}}n.exports={random:t,randomIterator:r}},{}],27:[function(e,n){function t(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=t},{}],28:[function(e,n){function t(e,n){var t=r(e);if(void 0===n)return t;for(var o=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},k=function(e){p=!1,r.off("touchmove",A),r.off("touchend",k),r.off("touchcancel",k),c=null,a&&a(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,r.on("touchmove",A),r.on("touchend",k),r.on("touchcancel",k))},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this -},onStop:function(e){return a=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),r.off("mousemove",w),r.off("mouseup",E),r.off("touchmove",A),r.off("touchend",k),r.off("touchcancel",k),P(null)}}}n.exports=t;var r=e("../Utils/documentEvents.js"),o=e("../Utils/browserInfo.js"),i=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":40,"../Utils/documentEvents.js":41,"../Utils/findElementPosition.js":42}],37:[function(e,n){function t(e,n){var t=r(n),o=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){o=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(o);var r=i[e.id];return r&&r.onStart&&r.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(o),o=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(o){var t=i[o.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=t;var r=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":58}],38:[function(e,n){function t(e,n){function t(e){return d[e]}n=r(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var a=o(n.seed),u=new i(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(){return{x:a.next(n.maxX),y:a.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n0)for(e=0;en,t)}),e.forEachNode(O),H(),e.on("changed",X)},K=function(){y=!1,H(),W(),a.off("resize",V),j.removeAllListeners(),l.stop(),e.forEachLink(function(e){n.renderLinks&&B(e)}),e.forEachNode(function(e){F(e),U(e)}),v.dispose(),z()};return{run:function(e){return y||(k(),S(),D(),G(),$(),y=!0),T(e),this},reset:function(){g.resetScale(),D(),A.scale=1},pause:function(){P=!0,l.stop()},resume:function(){P=!1,l.restart()},rerender:function(){return _(),this},zoomOut:function(){return J(!0)},zoomIn:function(){return J(!1)},moveTo:function(e,n){g.graphCenterChanged(A.offsetX-e*A.scale,A.offsetY-n*A.scale),_()},getGraphics:function(){return g},dispose:function(){K()},on:function(e,n){return j.addEventListener(e,n),this},off:function(e,n){return j.removeEventListener(e,n),this}}}n.exports=t;var r=e("ngraph.graph"),o=e("ngraph.forcelayout"),i=e("./svgGraphics.js"),a=e("../Utils/windowEvents.js"),u=e("../Input/domInputManager.js"),s=e("../Utils/timer.js"),f=e("../Utils/getDimensions.js"),c=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.forcelayout":7,"ngraph.graph":24}],50:[function(e,n){function t(){function e(){var e=r("svg");return n=r("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,a,u,s,f=1,c={},d={},l=function(){return r("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(){return r("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+a+","+u+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){a=e,u=n,w()},inputManager:i,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),s=n.getCTM().multiply(i);f=s.a,a=s.e,u=s.f;var c="matrix("+s.a+", 0, 0,"+s.d+","+s.e+","+s.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof s&&s(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):s=e),t},getSvgRoot:function(){return t}};return o(b),b}n.exports=t;var r=e("simplesvg"),o=e("ngraph.events"),i=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":35,"ngraph.events":6,simplesvg:28}],51:[function(e,n){function t(e){e=f(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,c,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=o(),P=i(),N=function(){return a()},A=function(){return u(3014898687)},k=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),c&&c.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(A=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:r,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,k()},addLink:function(e,n){var t=m++,r=A(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],k()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,k(),I(this),y[0]},resetScale:function(){return j(),c&&(_(),k()),this},init:function(r){var o={};if(e.preserveDrawingBuffer&&(o.preserveDrawingBuffer=!0),n=r,_(),j(),n.appendChild(t),c=t.getContext("experimental-webgl",o),!c){var i="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(i),i}if(e.enableBlending&&(c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA),c.enable(c.BLEND)),e.clearColor){var a=e.clearColorValue;c.clearColor(a.r,a.g,a.b,a.a),this.beginRender=function(){c.clear(c.COLOR_BUFFER_BIT)}}L.load(c),L.updateSize(d/2,l/2),P.load(c),P.updateSize(d/2,l/2),k(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!c&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!c&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return s(T),T}n.exports=t;var r=e("../Input/webglInputManager.js"),o=e("../WebGL/webglLinkProgram.js"),i=e("../WebGL/webglNodeProgram.js"),a=e("../WebGL/webglSquare.js"),u=e("../WebGL/webglLine.js"),s=e("ngraph.events"),f=e("ngraph.merge")},{"../Input/webglInputManager.js":37,"../WebGL/webglLine.js":59,"../WebGL/webglLinkProgram.js":60,"../WebGL/webglNodeProgram.js":61,"../WebGL/webglSquare.js":62,"ngraph.events":6,"ngraph.merge":25}],52:[function(e,n){function t(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=t},{}],53:[function(e,n){function t(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=t},{}],54:[function(e,n){function t(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function i(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function o(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=t},{}],55:[function(e,n){function t(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!r(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:i,getCoordinates:a,load:u};return E}function r(e){return 0===(e&e-1)}var o=e("./texture.js");n.exports=t},{"./texture.js":53}],56:[function(e,n){function t(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=t},{}],57:[function(e,n){function t(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=r(),A=o(),k=1024,j=0,_=new Float32Array(64);return{load:t,position:u,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function r(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function o(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var i=e("./webglAtlas.js"),a=e("./webgl.js");n.exports=t},{"./webgl.js":54,"./webglAtlas.js":55}],58:[function(e,n){function t(e){function n(){x=null}function t(e){x=e}function o(e){return"function"==typeof e&&A.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(A,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],A=[],k=e.getGraphicsRoot();h(k);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:o,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var r=e("../Utils/documentEvents.js");n.exports=t},{"../Utils/documentEvents.js":41}],59:[function(e,n){function t(e){return{color:r(e)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],60:[function(e,n){function t(){var e,n,t,o,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,o=r(a),e=o.createProgram(v,p),n.useProgram(e),i=o.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&o.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&o.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],61:[function(e,n){function t(){function e(){if((A+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=r(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function o(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){A>0&&(A-=1),e.id0&&v.copyArrayPart(N,e.id*x,A*x,x)}function u(){e(),A+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,A)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),A=0;return{load:n,position:t,updateTransform:o,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],62:[function(e,n){function t(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],63:[function(e,n){n.exports="0.7.4"},{}]},{},[1])(1)}); \ No newline at end of file +},onStop:function(e){return a=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),r.off("mousemove",w),r.off("mouseup",E),r.off("touchmove",A),r.off("touchend",k),r.off("touchcancel",k),P(null)}}}n.exports=t;var r=e("../Utils/documentEvents.js"),o=e("../Utils/browserInfo.js"),i=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":40,"../Utils/documentEvents.js":41,"../Utils/findElementPosition.js":42}],37:[function(e,n){function t(e,n){var t=r(n),o=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){o=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(o);var r=i[e.id];return r&&r.onStart&&r.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(o),o=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(o){var t=i[o.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=t;var r=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":58}],38:[function(e,n){function t(e,n){function t(e){return d[e]}n=r(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var a=o(n.seed),u=new i(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(){return{x:a.next(n.maxX),y:a.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n0)for(e=0;en,t)}),e.forEachNode(O),H(),e.on("changed",X)},K=function(){y=!1,H(),W(),a.off("resize",V),j.removeAllListeners(),l.stop(),e.forEachLink(function(e){n.renderLinks&&B(e)}),e.forEachNode(function(e){F(e),U(e)}),v.dispose(),z()};return{run:function(e){return y||(k(),S(),D(),G(),$(),y=!0),T(e),this},reset:function(){g.resetScale(),D(),A.scale=1},pause:function(){P=!0,l.stop()},resume:function(){P=!1,l.restart()},rerender:function(){return _(),this},zoomOut:function(){return J(!0)},zoomIn:function(){return J(!1)},moveTo:function(e,n){g.graphCenterChanged(A.offsetX-e*A.scale,A.offsetY-n*A.scale),_()},getGraphics:function(){return g},dispose:function(){K()},on:function(e,n){return j.addEventListener(e,n),this},off:function(e,n){return j.removeEventListener(e,n),this}}}n.exports=t;var r=e("ngraph.graph"),o=e("ngraph.forcelayout"),i=e("./svgGraphics.js"),a=e("../Utils/windowEvents.js"),u=e("../Input/domInputManager.js"),s=e("../Utils/timer.js"),f=e("../Utils/getDimensions.js"),c=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.forcelayout":7,"ngraph.graph":24}],50:[function(e,n){function t(){function e(){var e=r("svg");return n=r("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,a,u,s,f=1,c={},d={},l=function(){return r("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(){return r("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+a+","+u+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){a=e,u=n,w()},inputManager:i,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),s=n.getCTM().multiply(i);f=s.a,a=s.e,u=s.f;var c="matrix("+s.a+", 0, 0,"+s.d+","+s.e+","+s.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof s&&s(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):s=e),t},getSvgRoot:function(){return t}};return o(b),b}n.exports=t;var r=e("simplesvg"),o=e("ngraph.events"),i=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":35,"ngraph.events":6,simplesvg:28}],51:[function(e,n){function t(e){e=f(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,c,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=o(),P=i(),N=function(){return a()},A=function(){return u(3014898687)},k=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),c&&c.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(A=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:r,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,k()},addLink:function(e,n){var t=m++,r=A(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],k()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,k(),I(this),y[0]},resetScale:function(){return j(),c&&(_(),k()),this},init:function(r){var o={};if(e.preserveDrawingBuffer&&(o.preserveDrawingBuffer=!0),n=r,_(),j(),n.appendChild(t),c=t.getContext("experimental-webgl",o),!c){var i="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(i),i}if(e.enableBlending&&(c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA),c.enable(c.BLEND)),e.clearColor){var a=e.clearColorValue;c.clearColor(a.r,a.g,a.b,a.a),this.beginRender=function(){c.clear(c.COLOR_BUFFER_BIT)}}L.load(c),L.updateSize(d/2,l/2),P.load(c),P.updateSize(d/2,l/2),k(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!c&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!c&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return s(T),T}n.exports=t;var r=e("../Input/webglInputManager.js"),o=e("../WebGL/webglLinkProgram.js"),i=e("../WebGL/webglNodeProgram.js"),a=e("../WebGL/webglSquare.js"),u=e("../WebGL/webglLine.js"),s=e("ngraph.events"),f=e("ngraph.merge")},{"../Input/webglInputManager.js":37,"../WebGL/webglLine.js":59,"../WebGL/webglLinkProgram.js":60,"../WebGL/webglNodeProgram.js":61,"../WebGL/webglSquare.js":62,"ngraph.events":6,"ngraph.merge":25}],52:[function(e,n){function t(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=t},{}],53:[function(e,n){function t(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=t},{}],54:[function(e,n){function t(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function i(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function o(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=t},{}],55:[function(e,n){function t(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!r(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:i,getCoordinates:a,load:u};return E}function r(e){return 0===(e&e-1)}var o=e("./texture.js");n.exports=t},{"./texture.js":53}],56:[function(e,n){function t(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=t},{}],57:[function(e,n){function t(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=r(),A=o(),k=1024,j=0,_=new Float32Array(64);return{load:t,position:u,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function r(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function o(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var i=e("./webglAtlas.js"),a=e("./webgl.js");n.exports=t},{"./webgl.js":54,"./webglAtlas.js":55}],58:[function(e,n){function t(e){function n(){x=null}function t(e){x=e}function o(e){return"function"==typeof e&&A.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(A,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],A=[],k=e.getGraphicsRoot();h(k);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:o,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var r=e("../Utils/documentEvents.js");n.exports=t},{"../Utils/documentEvents.js":41}],59:[function(e,n){function t(e){return{color:r(e)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],60:[function(e,n){function t(){var e,n,t,o,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,o=r(a),e=o.createProgram(v,p),n.useProgram(e),i=o.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&o.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&o.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],61:[function(e,n){function t(){function e(){if((A+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=r(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function o(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){A>0&&(A-=1),e.id0&&v.copyArrayPart(N,e.id*x,A*x,x)}function u(){e(),A+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,A)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),A=0;return{load:n,position:t,updateTransform:o,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],62:[function(e,n){function t(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],63:[function(e,n){n.exports="0.7.5"},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index b3d9f4b..6ddbe83 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -3,7 +3,6 @@ var gutil = require('gulp-util'); var buffer = require('vinyl-buffer'); var source = require('vinyl-source-stream'); -var path = require('path'); var uglify = require('gulp-uglify'); var rename = require('gulp-rename'); var del = require('del'); @@ -45,52 +44,3 @@ function build() { gutil.log(gutil.colors.red('Failed to browserify'), gutil.colors.yellow(err.message)); } } - -function getFiles() { - // todo: this will be changed when we move to commonjs - return [ // core - "Utils/etc.js", - "Utils/browserInfo.js", - "Utils/indexOf.js", - "Utils/getDimensions.js", - "Utils/events.js", - "Input/spatialIndex.js", // TODO: Do I need this for SVG? - "Utils/timer.js", - "Utils/geom.js", - - "Core/primitives.js", - "Core/graph.js", - "Core/operations.js", - - "Physics/primitives.js", - "Physics/eulerIntegrator.js", - "Physics/Forces/nbodyForce.js", - "Physics/Forces/dragForce.js", - "Physics/Forces/springForce.js", - "Physics/forceSimulator.js", - "Layout/forceDirected.js", - "Layout/constant.js", - "View/renderer.js", - // extra - "Core/serializer.js", - "Algorithms/centrality.js", - "Algorithms/Community/community.js", - "Algorithms/Community/slpa.js", - "Core/generator.js", - // svg - "View/svgGraphics.js", - "View/svgNodeFactory.js", - // webgl - "WebGL/webgl.js", - "WebGL/webglUIModels.js", - "WebGL/webglNodeProgram.js", - "WebGL/webglLinkProgram.js", - "WebGL/webglImageNodeProgram.js", - "View/webglGraphics.js", - "WebGL/webglInputEvents.js", - "Input/webglInputManager.js"].map(toSrcFolder); -} - -function toSrcFolder(name) { - return path.join('src', name); -} From 979b533a13cc8f723e135a43debc956323bb593e Mon Sep 17 00:00:00 2001 From: anvaka Date: Tue, 3 Mar 2015 19:11:32 -0800 Subject: [PATCH 174/276] Removed anonymous function --- src/Input/domInputManager.js | 70 ++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/src/Input/domInputManager.js b/src/Input/domInputManager.js index 10862a6..48f6b5c 100644 --- a/src/Input/domInputManager.js +++ b/src/Input/domInputManager.js @@ -7,39 +7,41 @@ module.exports = domInputManager; var dragndrop = require('./dragndrop.js'); function domInputManager(graph, graphics) { - var nodeEvents = {}; - return { - /** - * Called by renderer to listen to drag-n-drop events from node. E.g. for SVG - * graphics we may listen to DOM events, whereas for WebGL the graphics - * should provide custom eventing mechanism. - * - * @param node - to be monitored. - * @param handlers - object with set of three callbacks: - * onStart: function(), - * onDrag: function(e, offset), - * onStop: function() - */ - bindDragNDrop : function (node, handlers) { - var events; - if (handlers) { - var nodeUI = graphics.getNodeUI(node.id); - events = dragndrop(nodeUI); - if (typeof handlers.onStart === 'function') { - events.onStart(handlers.onStart); - } - if (typeof handlers.onDrag === 'function') { - events.onDrag(handlers.onDrag); - } - if (typeof handlers.onStop === 'function') { - events.onStop(handlers.onStop); - } + var nodeEvents = {}; + return { + /** + * Called by renderer to listen to drag-n-drop events from node. E.g. for SVG + * graphics we may listen to DOM events, whereas for WebGL the graphics + * should provide custom eventing mechanism. + * + * @param node - to be monitored. + * @param handlers - object with set of three callbacks: + * onStart: function(), + * onDrag: function(e, offset), + * onStop: function() + */ + bindDragNDrop: bindDragNDrop + }; - nodeEvents[node.id] = events; - } else if (( events = nodeEvents[node.id] )) { - events.release(); - delete nodeEvents[node.id]; - } - } - }; + function bindDragNDrop(node, handlers) { + var events; + if (handlers) { + var nodeUI = graphics.getNodeUI(node.id); + events = dragndrop(nodeUI); + if (typeof handlers.onStart === 'function') { + events.onStart(handlers.onStart); + } + if (typeof handlers.onDrag === 'function') { + events.onDrag(handlers.onDrag); + } + if (typeof handlers.onStop === 'function') { + events.onStop(handlers.onStop); + } + + nodeEvents[node.id] = events; + } else if ((events = nodeEvents[node.id])) { + events.release(); + delete nodeEvents[node.id]; + } + } } From 346afacc6e6acef3a4bbc78f4ac5863a925326d3 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 8 Mar 2015 09:15:59 -0700 Subject: [PATCH 175/276] Fixed graph disposal. Added example Fix for https://github.com/anvaka/VivaGraphJS/issues/128 --- demos/other/remove-graph/README.md | 11 +++++ demos/other/remove-graph/index.html | 38 +++++++++++++++ demos/other/remove-graph/index.js | 32 +++++++++++++ dist/vivagraph.js | 74 +++++++++++++++-------------- dist/vivagraph.min.js | 4 +- src/View/renderer.js | 2 +- src/version.js | 2 +- 7 files changed, 123 insertions(+), 40 deletions(-) create mode 100644 demos/other/remove-graph/README.md create mode 100644 demos/other/remove-graph/index.html create mode 100644 demos/other/remove-graph/index.js diff --git a/demos/other/remove-graph/README.md b/demos/other/remove-graph/README.md new file mode 100644 index 0000000..0e4f21c --- /dev/null +++ b/demos/other/remove-graph/README.md @@ -0,0 +1,11 @@ +# Remove graph + +This demo shows how to completely remove graph from the DOM. + +# How it is done? + +``` js +// renderer is created as Viva.Graph.View.renderer() +// if you no longer need it just call: +renderer.dispose(); +``` diff --git a/demos/other/remove-graph/index.html b/demos/other/remove-graph/index.html new file mode 100644 index 0000000..ac66259 --- /dev/null +++ b/demos/other/remove-graph/index.html @@ -0,0 +1,38 @@ + + + + + + VivaGraph remove graph + + + + + + + + +
+ + + diff --git a/demos/other/remove-graph/index.js b/demos/other/remove-graph/index.js new file mode 100644 index 0000000..c686ca2 --- /dev/null +++ b/demos/other/remove-graph/index.js @@ -0,0 +1,32 @@ +/** + * This demo shows how to dispose renderer and create a new one. + */ +function removeGraph() { + if (!window.renderer) { + return; // already removed + } + window.renderer.dispose(); // remove the graph + window.renderer = null; +} + +function createNewGraph() { + removeGraph(); + // just a random size for a grid graph [1, 9): + var n = Math.random() * 10|0 + 1; + var m = Math.random() * 10|0 + 1; + var graph = Viva.Graph.generator().grid(n, m); + + window.renderer = Viva.Graph.View.renderer(graph, { + layout : createPhysicsLayout(graph) + }); + window.renderer.run(); +} + +function createPhysicsLayout(graph) { + return Viva.Graph.Layout.forceDirected(graph, { + springLength : 10, + springCoeff : 0.0005, + dragCoeff : 0.02, + gravity : -1.2 + }); +} diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 7ab881a..de83936 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -3267,41 +3267,43 @@ module.exports = domInputManager; var dragndrop = require('./dragndrop.js'); function domInputManager(graph, graphics) { - var nodeEvents = {}; - return { - /** - * Called by renderer to listen to drag-n-drop events from node. E.g. for SVG - * graphics we may listen to DOM events, whereas for WebGL the graphics - * should provide custom eventing mechanism. - * - * @param node - to be monitored. - * @param handlers - object with set of three callbacks: - * onStart: function(), - * onDrag: function(e, offset), - * onStop: function() - */ - bindDragNDrop : function (node, handlers) { - var events; - if (handlers) { - var nodeUI = graphics.getNodeUI(node.id); - events = dragndrop(nodeUI); - if (typeof handlers.onStart === 'function') { - events.onStart(handlers.onStart); - } - if (typeof handlers.onDrag === 'function') { - events.onDrag(handlers.onDrag); - } - if (typeof handlers.onStop === 'function') { - events.onStop(handlers.onStop); - } + var nodeEvents = {}; + return { + /** + * Called by renderer to listen to drag-n-drop events from node. E.g. for SVG + * graphics we may listen to DOM events, whereas for WebGL the graphics + * should provide custom eventing mechanism. + * + * @param node - to be monitored. + * @param handlers - object with set of three callbacks: + * onStart: function(), + * onDrag: function(e, offset), + * onStop: function() + */ + bindDragNDrop: bindDragNDrop + }; - nodeEvents[node.id] = events; - } else if (( events = nodeEvents[node.id] )) { - events.release(); - delete nodeEvents[node.id]; - } - } - }; + function bindDragNDrop(node, handlers) { + var events; + if (handlers) { + var nodeUI = graphics.getNodeUI(node.id); + events = dragndrop(nodeUI); + if (typeof handlers.onStart === 'function') { + events.onStart(handlers.onStart); + } + if (typeof handlers.onDrag === 'function') { + events.onDrag(handlers.onDrag); + } + if (typeof handlers.onStop === 'function') { + events.onStop(handlers.onStop); + } + + nodeEvents[node.id] = events; + } else if ((events = nodeEvents[node.id])) { + events.release(); + delete nodeEvents[node.id]; + } + } } },{"./dragndrop.js":36}],36:[function(require,module,exports){ @@ -4513,7 +4515,7 @@ function renderer(graph, settings) { releaseGraphEvents(); releaseContainerDragManager(); windowEvents.off('resize', onWindowResized); - publicEvents.removeAllListeners(); + publicEvents.off(); animationTimer.stop(); graph.forEachLink(function (link) { @@ -6800,7 +6802,7 @@ function webglSquare(size, color) { },{"./parseColor.js":52}],63:[function(require,module,exports){ // todo: this should be generated at build time. -module.exports = '0.7.5'; +module.exports = '0.7.6'; },{}]},{},[1])(1) }); \ No newline at end of file diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 52c834d..2ac90a8 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-s*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=t},{}],3:[function(e,n){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n){function t(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function g(e){var n=w[e];n.mass=y(e)}function h(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function m(e){var n=w[e];return n||(c(e),n=w[e]),n}function y(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var x=e("ngraph.physics.simulator");t=t||x(),o(t,"physicsSimulator").has("step","getBestNewBodyPosition","addBodyAt");var w="function"==typeof Object.create?Object.create(null):{},b={},E=t.settings.springTransform||r;f(),u();var L={step:function(){return t.step()},getNodePosition:function(e){return m(e).pos},setNodePosition:function(e){var n=m(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return t.getBBox()},pinNode:function(e,n){var t=m(e.id);t.isPinned=!!n},isNodePinned:function(e){return m(e.id).isPinned},dispose:function(){n.off("changed",s)},getBody:a,getSpring:i,simulator:t};return L}function r(){}n.exports=t,n.exports.simulator=e("ngraph.physics.simulator");var o=e("varta")},{"ngraph.physics.simulator":8,varta:21}],8:[function(e,n){function t(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.force.reset(),v.updateBodyForce(e),m.update(e);for(n=p.length;n--;)h.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),u=n.createBounds||e("./lib/bounds"),s=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),g=u(l,n),h=f(n),m=s(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return g.update(),en))return l.splice(n,1),0===l.length&&g.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return g.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=t},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":25,"ngraph.quadtreebh":17}],9:[function(e,n){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;ut;++t){var s=e[t],f=n/s.mass;s.velocity.x+=f*s.force.x,s.velocity.y+=f*s.force.y;var c=s.velocity.x,d=s.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=t},{}],13:[function(e,n){function t(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=t},{}],14:[function(e,n){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":25,"ngraph.random":26}],15:[function(e,n){function t(e,n,t){var o="[object Array]"===Object.prototype.toString.call(t);if(o)for(var i=0;i0&&u(s.pos,a.pos));if(0===f&&u(s.pos,a.pos))return}c.push(i,s),c.push(i,a)}else{var h=a.pos.x,m=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*h,i.massY=i.massY+a.mass*m;var y=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;if(h>w){y+=1;var L=x;x=w,w+=w-L}if(m>E){y+=2;var P=b;b=E,E+=E-P}var N=t(i,y);N?c.push(N,a):(N=v(),N.left=x,N.top=b,N.right=w,N.bottom=E,N.body=a,r(i,y,N))}}},m=function(e){var n,t,r,i,a=f,u=0,c=0,l=1,p=0,v=1;for(a[0]=g;l;){var h=a[p],m=h.body;l-=1,p+=1;var y=m!==e;m&&y?(t=m.pos.x-e.pos.x,r=m.pos.y-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),n=s*m.mass*e.mass/(i*i*i),u+=n*t,c+=n*r):y&&(t=h.massX/h.mass-e.pos.x,r=h.massY/h.mass-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),(h.right-h.left)/iu&&(t=u),u>o&&(o=u),r>s&&(r=s),s>i&&(i=s)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,p=0,g=v(),g.left=t,g.right=o,g.top=r,g.bottom=i,n=a-1,n>0&&(g.body=e[n]);n--;)h(e[n],g)};return{insertBodies:y,updateBodyForce:m,options:function(e){return e?("number"==typeof e.gravity&&(s=e.gravity),"number"==typeof e.theta&&(d=e.theta),this):{gravity:s,theta:d}}}}},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":26}],18:[function(e,n){function t(){this.stack=[],this.popIdx=0}function r(e,n){this.node=e,this.body=n}n.exports=t,t.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new r(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],19:[function(e,n){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],20:[function(e,n){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],21:[function(e,n){function t(e,n){function t(){return o(e,n,arguments)}return n=n||"Argument",{has:t}}function r(){function e(e,t){return o(e,t,n)}var n=arguments;return e}function o(e,n,t){if(void 0===e)throw new Error(n+" is not defined");for(var r=0;re)throw new Error("Invalid number of nodes");var n,t=l();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function r(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=t(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function o(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=l();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function i(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=l();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function a(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=l();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function u(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=l();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function s(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=l();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var u=i*e*n,s=r+o*e+u;r>0&&a.addLink(s,r-1+o*e+u),o>0&&a.addLink(s,r+(o-1)*e+u),i>0&&a.addLink(s,r+o*e+(i-1)*e*n)}return a}function f(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=l(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function c(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=l();for(n=0;e>n;++n)t.addNode(n);return t}function d(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,u=e("ngraph.random").random(o||42),s=l();for(i=0;n>i;++i)s.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,s.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(u.nextDouble()n)return!1;S(),P.splice(n,1);var t=s(e.fromId),o=s(e.toId);return t&&(n=r(e,t.links),n>=0&&t.links.splice(n,1)),o&&(n=r(e,o.links),n>=0&&o.links.splice(n,1)),T(e,"remove"),D(),!0}function p(e,n){var t,r=s(e);if(!r)return null;for(t=0;tn;++n)e(P[n])}function h(e,n,t){var r,o,i,a=s(e);if(a&&a.links&&"function"==typeof n)if(t)for(r=0;r0&&(M.fire("changed",I),I.length=0)}function w(){return Object.keys?b:E}function b(e){if("function"==typeof e)for(var n=Object.keys(L),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function o(e){this.id=e,this.links=[],this.data=null}function i(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=t;var a=e("ngraph.events")},{"ngraph.events":6}],25:[function(e,n){function t(e,n){var r;if(e||(e={}),n)for(r in n)if(n.hasOwnProperty(r)){var o=e.hasOwnProperty(r),i=typeof n[r],a=!o||typeof e[r]!==i;a?e[r]=n[r]:"object"===i&&(e[r]=t(e[r],n[r]))}return e}n.exports=t},{}],26:[function(e,n){function t(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function r(e,n){var r=n||t();if("function"!=typeof r.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var t,o,i;for(t=e.length-1;t>0;--t)o=r.next(t+1),i=e[o],e[o]=e[t],e[t]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,t,o;for(n=e.length-1;n>0;--n)t=r.next(n+1),o=e[t],e[t]=e[n],e[n]=o;return e}}}n.exports={random:t,randomIterator:r}},{}],27:[function(e,n){function t(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=t},{}],28:[function(e,n){function t(e,n){var t=r(e);if(void 0===n)return t;for(var o=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},k=function(e){p=!1,r.off("touchmove",A),r.off("touchend",k),r.off("touchcancel",k),c=null,a&&a(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,r.on("touchmove",A),r.on("touchend",k),r.on("touchcancel",k))},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this -},onStop:function(e){return a=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),r.off("mousemove",w),r.off("mouseup",E),r.off("touchmove",A),r.off("touchend",k),r.off("touchcancel",k),P(null)}}}n.exports=t;var r=e("../Utils/documentEvents.js"),o=e("../Utils/browserInfo.js"),i=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":40,"../Utils/documentEvents.js":41,"../Utils/findElementPosition.js":42}],37:[function(e,n){function t(e,n){var t=r(n),o=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){o=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(o);var r=i[e.id];return r&&r.onStart&&r.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(o),o=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(o){var t=i[o.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=t;var r=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":58}],38:[function(e,n){function t(e,n){function t(e){return d[e]}n=r(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var a=o(n.seed),u=new i(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(){return{x:a.next(n.maxX),y:a.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n0)for(e=0;en,t)}),e.forEachNode(O),H(),e.on("changed",X)},K=function(){y=!1,H(),W(),a.off("resize",V),j.removeAllListeners(),l.stop(),e.forEachLink(function(e){n.renderLinks&&B(e)}),e.forEachNode(function(e){F(e),U(e)}),v.dispose(),z()};return{run:function(e){return y||(k(),S(),D(),G(),$(),y=!0),T(e),this},reset:function(){g.resetScale(),D(),A.scale=1},pause:function(){P=!0,l.stop()},resume:function(){P=!1,l.restart()},rerender:function(){return _(),this},zoomOut:function(){return J(!0)},zoomIn:function(){return J(!1)},moveTo:function(e,n){g.graphCenterChanged(A.offsetX-e*A.scale,A.offsetY-n*A.scale),_()},getGraphics:function(){return g},dispose:function(){K()},on:function(e,n){return j.addEventListener(e,n),this},off:function(e,n){return j.removeEventListener(e,n),this}}}n.exports=t;var r=e("ngraph.graph"),o=e("ngraph.forcelayout"),i=e("./svgGraphics.js"),a=e("../Utils/windowEvents.js"),u=e("../Input/domInputManager.js"),s=e("../Utils/timer.js"),f=e("../Utils/getDimensions.js"),c=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.forcelayout":7,"ngraph.graph":24}],50:[function(e,n){function t(){function e(){var e=r("svg");return n=r("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,a,u,s,f=1,c={},d={},l=function(){return r("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(){return r("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+a+","+u+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){a=e,u=n,w()},inputManager:i,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),s=n.getCTM().multiply(i);f=s.a,a=s.e,u=s.f;var c="matrix("+s.a+", 0, 0,"+s.d+","+s.e+","+s.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof s&&s(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):s=e),t},getSvgRoot:function(){return t}};return o(b),b}n.exports=t;var r=e("simplesvg"),o=e("ngraph.events"),i=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":35,"ngraph.events":6,simplesvg:28}],51:[function(e,n){function t(e){e=f(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,c,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=o(),P=i(),N=function(){return a()},A=function(){return u(3014898687)},k=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),c&&c.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(A=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:r,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,k()},addLink:function(e,n){var t=m++,r=A(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],k()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,k(),I(this),y[0]},resetScale:function(){return j(),c&&(_(),k()),this},init:function(r){var o={};if(e.preserveDrawingBuffer&&(o.preserveDrawingBuffer=!0),n=r,_(),j(),n.appendChild(t),c=t.getContext("experimental-webgl",o),!c){var i="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(i),i}if(e.enableBlending&&(c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA),c.enable(c.BLEND)),e.clearColor){var a=e.clearColorValue;c.clearColor(a.r,a.g,a.b,a.a),this.beginRender=function(){c.clear(c.COLOR_BUFFER_BIT)}}L.load(c),L.updateSize(d/2,l/2),P.load(c),P.updateSize(d/2,l/2),k(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!c&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!c&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return s(T),T}n.exports=t;var r=e("../Input/webglInputManager.js"),o=e("../WebGL/webglLinkProgram.js"),i=e("../WebGL/webglNodeProgram.js"),a=e("../WebGL/webglSquare.js"),u=e("../WebGL/webglLine.js"),s=e("ngraph.events"),f=e("ngraph.merge")},{"../Input/webglInputManager.js":37,"../WebGL/webglLine.js":59,"../WebGL/webglLinkProgram.js":60,"../WebGL/webglNodeProgram.js":61,"../WebGL/webglSquare.js":62,"ngraph.events":6,"ngraph.merge":25}],52:[function(e,n){function t(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=t},{}],53:[function(e,n){function t(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=t},{}],54:[function(e,n){function t(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function i(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function o(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=t},{}],55:[function(e,n){function t(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!r(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:i,getCoordinates:a,load:u};return E}function r(e){return 0===(e&e-1)}var o=e("./texture.js");n.exports=t},{"./texture.js":53}],56:[function(e,n){function t(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=t},{}],57:[function(e,n){function t(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=r(),A=o(),k=1024,j=0,_=new Float32Array(64);return{load:t,position:u,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function r(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function o(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var i=e("./webglAtlas.js"),a=e("./webgl.js");n.exports=t},{"./webgl.js":54,"./webglAtlas.js":55}],58:[function(e,n){function t(e){function n(){x=null}function t(e){x=e}function o(e){return"function"==typeof e&&A.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(A,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],A=[],k=e.getGraphicsRoot();h(k);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:o,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var r=e("../Utils/documentEvents.js");n.exports=t},{"../Utils/documentEvents.js":41}],59:[function(e,n){function t(e){return{color:r(e)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],60:[function(e,n){function t(){var e,n,t,o,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,o=r(a),e=o.createProgram(v,p),n.useProgram(e),i=o.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&o.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&o.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],61:[function(e,n){function t(){function e(){if((A+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=r(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function o(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){A>0&&(A-=1),e.id0&&v.copyArrayPart(N,e.id*x,A*x,x)}function u(){e(),A+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,A)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),A=0;return{load:n,position:t,updateTransform:o,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],62:[function(e,n){function t(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],63:[function(e,n){n.exports="0.7.5"},{}]},{},[1])(1)}); \ No newline at end of file +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-s*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=t},{}],3:[function(e,n){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n){function t(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function g(e){var n=w[e];n.mass=y(e)}function h(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function m(e){var n=w[e];return n||(c(e),n=w[e]),n}function y(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var x=e("ngraph.physics.simulator");t=t||x(),o(t,"physicsSimulator").has("step","getBestNewBodyPosition","addBodyAt");var w="function"==typeof Object.create?Object.create(null):{},b={},E=t.settings.springTransform||r;f(),u();var L={step:function(){return t.step()},getNodePosition:function(e){return m(e).pos},setNodePosition:function(e){var n=m(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return t.getBBox()},pinNode:function(e,n){var t=m(e.id);t.isPinned=!!n},isNodePinned:function(e){return m(e.id).isPinned},dispose:function(){n.off("changed",s)},getBody:a,getSpring:i,simulator:t};return L}function r(){}n.exports=t,n.exports.simulator=e("ngraph.physics.simulator");var o=e("varta")},{"ngraph.physics.simulator":8,varta:21}],8:[function(e,n){function t(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.force.reset(),v.updateBodyForce(e),m.update(e);for(n=p.length;n--;)h.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),u=n.createBounds||e("./lib/bounds"),s=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),g=u(l,n),h=f(n),m=s(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return g.update(),en))return l.splice(n,1),0===l.length&&g.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return g.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=t},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":25,"ngraph.quadtreebh":17}],9:[function(e,n){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;ut;++t){var s=e[t],f=n/s.mass;s.velocity.x+=f*s.force.x,s.velocity.y+=f*s.force.y;var c=s.velocity.x,d=s.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=t},{}],13:[function(e,n){function t(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=t},{}],14:[function(e,n){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":25,"ngraph.random":26}],15:[function(e,n){function t(e,n,t){var o="[object Array]"===Object.prototype.toString.call(t);if(o)for(var i=0;i0&&u(s.pos,a.pos));if(0===f&&u(s.pos,a.pos))return}c.push(i,s),c.push(i,a)}else{var h=a.pos.x,m=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*h,i.massY=i.massY+a.mass*m;var y=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;if(h>w){y+=1;var L=x;x=w,w+=w-L}if(m>E){y+=2;var P=b;b=E,E+=E-P}var N=t(i,y);N?c.push(N,a):(N=v(),N.left=x,N.top=b,N.right=w,N.bottom=E,N.body=a,r(i,y,N))}}},m=function(e){var n,t,r,i,a=f,u=0,c=0,l=1,p=0,v=1;for(a[0]=g;l;){var h=a[p],m=h.body;l-=1,p+=1;var y=m!==e;m&&y?(t=m.pos.x-e.pos.x,r=m.pos.y-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),n=s*m.mass*e.mass/(i*i*i),u+=n*t,c+=n*r):y&&(t=h.massX/h.mass-e.pos.x,r=h.massY/h.mass-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),(h.right-h.left)/iu&&(t=u),u>o&&(o=u),r>s&&(r=s),s>i&&(i=s)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,p=0,g=v(),g.left=t,g.right=o,g.top=r,g.bottom=i,n=a-1,n>0&&(g.body=e[n]);n--;)h(e[n],g)};return{insertBodies:y,updateBodyForce:m,options:function(e){return e?("number"==typeof e.gravity&&(s=e.gravity),"number"==typeof e.theta&&(d=e.theta),this):{gravity:s,theta:d}}}}},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":26}],18:[function(e,n){function t(){this.stack=[],this.popIdx=0}function r(e,n){this.node=e,this.body=n}n.exports=t,t.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new r(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],19:[function(e,n){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],20:[function(e,n){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],21:[function(e,n){function t(e,n){function t(){return o(e,n,arguments)}return n=n||"Argument",{has:t}}function r(){function e(e,t){return o(e,t,n)}var n=arguments;return e}function o(e,n,t){if(void 0===e)throw new Error(n+" is not defined");for(var r=0;re)throw new Error("Invalid number of nodes");var n,t=l();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function r(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=t(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function o(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=l();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function i(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=l();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function a(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=l();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function u(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=l();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function s(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=l();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var u=i*e*n,s=r+o*e+u;r>0&&a.addLink(s,r-1+o*e+u),o>0&&a.addLink(s,r+(o-1)*e+u),i>0&&a.addLink(s,r+o*e+(i-1)*e*n)}return a}function f(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=l(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function c(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=l();for(n=0;e>n;++n)t.addNode(n);return t}function d(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,u=e("ngraph.random").random(o||42),s=l();for(i=0;n>i;++i)s.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,s.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(u.nextDouble()n)return!1;S(),P.splice(n,1);var t=s(e.fromId),o=s(e.toId);return t&&(n=r(e,t.links),n>=0&&t.links.splice(n,1)),o&&(n=r(e,o.links),n>=0&&o.links.splice(n,1)),T(e,"remove"),D(),!0}function p(e,n){var t,r=s(e);if(!r)return null;for(t=0;tn;++n)e(P[n])}function h(e,n,t){var r,o,i,a=s(e);if(a&&a.links&&"function"==typeof n)if(t)for(r=0;r0&&(M.fire("changed",I),I.length=0)}function w(){return Object.keys?b:E}function b(e){if("function"==typeof e)for(var n=Object.keys(L),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function o(e){this.id=e,this.links=[],this.data=null}function i(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=t;var a=e("ngraph.events")},{"ngraph.events":6}],25:[function(e,n){function t(e,n){var r;if(e||(e={}),n)for(r in n)if(n.hasOwnProperty(r)){var o=e.hasOwnProperty(r),i=typeof n[r],a=!o||typeof e[r]!==i;a?e[r]=n[r]:"object"===i&&(e[r]=t(e[r],n[r]))}return e}n.exports=t},{}],26:[function(e,n){function t(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function r(e,n){var r=n||t();if("function"!=typeof r.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var t,o,i;for(t=e.length-1;t>0;--t)o=r.next(t+1),i=e[o],e[o]=e[t],e[t]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,t,o;for(n=e.length-1;n>0;--n)t=r.next(n+1),o=e[t],e[t]=e[n],e[n]=o;return e}}}n.exports={random:t,randomIterator:r}},{}],27:[function(e,n){function t(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=t},{}],28:[function(e,n){function t(e,n){var t=r(e);if(void 0===n)return t;for(var o=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},k=function(e){p=!1,r.off("touchmove",A),r.off("touchend",k),r.off("touchcancel",k),c=null,a&&a(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,r.on("touchmove",A),r.on("touchend",k),r.on("touchcancel",k))},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this +},onStop:function(e){return a=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),r.off("mousemove",w),r.off("mouseup",E),r.off("touchmove",A),r.off("touchend",k),r.off("touchcancel",k),P(null)}}}n.exports=t;var r=e("../Utils/documentEvents.js"),o=e("../Utils/browserInfo.js"),i=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":40,"../Utils/documentEvents.js":41,"../Utils/findElementPosition.js":42}],37:[function(e,n){function t(e,n){var t=r(n),o=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){o=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(o);var r=i[e.id];return r&&r.onStart&&r.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(o),o=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(o){var t=i[o.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=t;var r=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":58}],38:[function(e,n){function t(e,n){function t(e){return d[e]}n=r(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var a=o(n.seed),u=new i(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(){return{x:a.next(n.maxX),y:a.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n0)for(e=0;en,t)}),e.forEachNode(O),H(),e.on("changed",X)},K=function(){y=!1,H(),W(),a.off("resize",V),j.off(),l.stop(),e.forEachLink(function(e){n.renderLinks&&B(e)}),e.forEachNode(function(e){F(e),U(e)}),v.dispose(),z()};return{run:function(e){return y||(k(),S(),D(),G(),$(),y=!0),T(e),this},reset:function(){g.resetScale(),D(),A.scale=1},pause:function(){P=!0,l.stop()},resume:function(){P=!1,l.restart()},rerender:function(){return _(),this},zoomOut:function(){return J(!0)},zoomIn:function(){return J(!1)},moveTo:function(e,n){g.graphCenterChanged(A.offsetX-e*A.scale,A.offsetY-n*A.scale),_()},getGraphics:function(){return g},dispose:function(){K()},on:function(e,n){return j.addEventListener(e,n),this},off:function(e,n){return j.removeEventListener(e,n),this}}}n.exports=t;var r=e("ngraph.graph"),o=e("ngraph.forcelayout"),i=e("./svgGraphics.js"),a=e("../Utils/windowEvents.js"),u=e("../Input/domInputManager.js"),s=e("../Utils/timer.js"),f=e("../Utils/getDimensions.js"),c=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.forcelayout":7,"ngraph.graph":24}],50:[function(e,n){function t(){function e(){var e=r("svg");return n=r("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,a,u,s,f=1,c={},d={},l=function(){return r("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(){return r("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+a+","+u+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){a=e,u=n,w()},inputManager:i,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),s=n.getCTM().multiply(i);f=s.a,a=s.e,u=s.f;var c="matrix("+s.a+", 0, 0,"+s.d+","+s.e+","+s.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof s&&s(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):s=e),t},getSvgRoot:function(){return t}};return o(b),b}n.exports=t;var r=e("simplesvg"),o=e("ngraph.events"),i=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":35,"ngraph.events":6,simplesvg:28}],51:[function(e,n){function t(e){e=f(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,c,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=o(),P=i(),N=function(){return a()},A=function(){return u(3014898687)},k=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),c&&c.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(A=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:r,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,k()},addLink:function(e,n){var t=m++,r=A(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],k()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,k(),I(this),y[0]},resetScale:function(){return j(),c&&(_(),k()),this},init:function(r){var o={};if(e.preserveDrawingBuffer&&(o.preserveDrawingBuffer=!0),n=r,_(),j(),n.appendChild(t),c=t.getContext("experimental-webgl",o),!c){var i="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(i),i}if(e.enableBlending&&(c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA),c.enable(c.BLEND)),e.clearColor){var a=e.clearColorValue;c.clearColor(a.r,a.g,a.b,a.a),this.beginRender=function(){c.clear(c.COLOR_BUFFER_BIT)}}L.load(c),L.updateSize(d/2,l/2),P.load(c),P.updateSize(d/2,l/2),k(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!c&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!c&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return s(T),T}n.exports=t;var r=e("../Input/webglInputManager.js"),o=e("../WebGL/webglLinkProgram.js"),i=e("../WebGL/webglNodeProgram.js"),a=e("../WebGL/webglSquare.js"),u=e("../WebGL/webglLine.js"),s=e("ngraph.events"),f=e("ngraph.merge")},{"../Input/webglInputManager.js":37,"../WebGL/webglLine.js":59,"../WebGL/webglLinkProgram.js":60,"../WebGL/webglNodeProgram.js":61,"../WebGL/webglSquare.js":62,"ngraph.events":6,"ngraph.merge":25}],52:[function(e,n){function t(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=t},{}],53:[function(e,n){function t(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=t},{}],54:[function(e,n){function t(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function i(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function o(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=t},{}],55:[function(e,n){function t(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!r(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:i,getCoordinates:a,load:u};return E}function r(e){return 0===(e&e-1)}var o=e("./texture.js");n.exports=t},{"./texture.js":53}],56:[function(e,n){function t(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=t},{}],57:[function(e,n){function t(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=r(),A=o(),k=1024,j=0,_=new Float32Array(64);return{load:t,position:u,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function r(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function o(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var i=e("./webglAtlas.js"),a=e("./webgl.js");n.exports=t},{"./webgl.js":54,"./webglAtlas.js":55}],58:[function(e,n){function t(e){function n(){x=null}function t(e){x=e}function o(e){return"function"==typeof e&&A.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(A,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],A=[],k=e.getGraphicsRoot();h(k);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:o,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var r=e("../Utils/documentEvents.js");n.exports=t},{"../Utils/documentEvents.js":41}],59:[function(e,n){function t(e){return{color:r(e)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],60:[function(e,n){function t(){var e,n,t,o,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,o=r(a),e=o.createProgram(v,p),n.useProgram(e),i=o.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&o.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&o.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],61:[function(e,n){function t(){function e(){if((A+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=r(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function o(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){A>0&&(A-=1),e.id0&&v.copyArrayPart(N,e.id*x,A*x,x)}function u(){e(),A+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,A)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),A=0;return{load:n,position:t,updateTransform:o,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],62:[function(e,n){function t(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],63:[function(e,n){n.exports="0.7.6"},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/src/View/renderer.js b/src/View/renderer.js index e0dba98..7566c4a 100644 --- a/src/View/renderer.js +++ b/src/View/renderer.js @@ -355,7 +355,7 @@ function renderer(graph, settings) { releaseGraphEvents(); releaseContainerDragManager(); windowEvents.off('resize', onWindowResized); - publicEvents.removeAllListeners(); + publicEvents.off(); animationTimer.stop(); graph.forEachLink(function (link) { diff --git a/src/version.js b/src/version.js index d960c51..6a8db6d 100644 --- a/src/version.js +++ b/src/version.js @@ -1,2 +1,2 @@ // todo: this should be generated at build time. -module.exports = '0.7.5'; +module.exports = '0.7.6'; From 002271a494996ced0ab0d00b0225be3221abd83f Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 8 Mar 2015 09:16:17 -0700 Subject: [PATCH 176/276] 0.7.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ea5d121..a21bc4d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.7.5", + "version": "0.7.6", "description": "Graph Drawing Library", "main": "src/viva", "directories": { From ad11eaed4f67df1a44c99d7980374fc1bb392870 Mon Sep 17 00:00:00 2001 From: Andrei Kashcha Date: Sun, 8 Mar 2015 09:19:33 -0700 Subject: [PATCH 177/276] Update README.md --- demos/other/remove-graph/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/demos/other/remove-graph/README.md b/demos/other/remove-graph/README.md index 0e4f21c..c16a02f 100644 --- a/demos/other/remove-graph/README.md +++ b/demos/other/remove-graph/README.md @@ -9,3 +9,5 @@ This demo shows how to completely remove graph from the DOM. // if you no longer need it just call: renderer.dispose(); ``` + +[See online demo](http://anvaka.github.io/VivaGraphJS/demos/other/remove-graph/) From 76d0beffe56fca7e1aa6f6370c07f287a56057de Mon Sep 17 00:00:00 2001 From: anvaka Date: Fri, 13 Mar 2015 20:17:24 -0700 Subject: [PATCH 178/276] Fixed broken link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cfe5a99..3b91ee7 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Some examples of library usage in the real projects: * [YouTube Visualization](http://www.yasiv.com/youtube#/Search?q=write%20in%20c) Shows related videos from YouTube. SVG based. * [Facebook Visualization](http://www.yasiv.com/facebook) friendship visualization on Facebook. WebGL based. * [Graph Viewer](http://www.yasiv.com/graphs#Bai/rw496) visualization of sparse matrices collection of the University of Florida. WebGL based. -* [Vkontakte Visualization](http://www.yasiv.com/vk) friendship visualization of the largest social network in Russia [vk.com](vk.com). WebGL based. +* [Vkontakte Visualization](http://www.yasiv.com/vk) friendship visualization of the largest social network in Russia [vk.com](https://vk.com). WebGL based. To start using the library include `vivagraph.js` script from the [dist](https://github.com/anvaka/VivaGraphJS/tree/master/dist) folder. The following code is the minimum required to render a graph with two nodes and one edge: From 831ed1d82eb82309ef80deb6b8374c2768b2ad39 Mon Sep 17 00:00:00 2001 From: anvaka Date: Tue, 24 Mar 2015 21:06:44 -0700 Subject: [PATCH 179/276] Updated dependencies --- package.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index a21bc4d..10f3c8f 100644 --- a/package.json +++ b/package.json @@ -33,15 +33,15 @@ }, "dependencies": { "gintersect": "0.1.0", - "ngraph.centrality": "0.1.1", + "ngraph.centrality": "0.1.2", "ngraph.events": "0.0.3", - "ngraph.forcelayout": "0.0.16", - "ngraph.fromjson": "0.1.4", - "ngraph.generators": "0.0.13", - "ngraph.graph": "0.0.8", + "ngraph.forcelayout": "0.0.17", + "ngraph.fromjson": "0.1.6", + "ngraph.generators": "0.0.14", + "ngraph.graph": "0.0.10", "ngraph.merge": "0.0.1", "ngraph.random": "0.0.1", - "ngraph.tojson": "0.1.1", + "ngraph.tojson": "0.1.2", "simplesvg": "0.0.10" } } From 9d96bed02c7e2071093a4e06f3bf268c41f78737 Mon Sep 17 00:00:00 2001 From: anvaka Date: Tue, 24 Mar 2015 21:11:30 -0700 Subject: [PATCH 180/276] Formatting --- demos/other/webgl-area-select/README.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/demos/other/webgl-area-select/README.md b/demos/other/webgl-area-select/README.md index ac6a3fe..a5fd3c6 100644 --- a/demos/other/webgl-area-select/README.md +++ b/demos/other/webgl-area-select/README.md @@ -11,8 +11,14 @@ First of all we create a basic div overlay on top of graph container:
``` -Overlay element should have exactly the same size/position as grpah container. In this demo we are using absolute position for `.graph-overlay` and explicitly positioned common parent (`body`). See more details here: [How to overlay one div over another div](http://stackoverflow.com/questions/2941189/how-to-overlay-one-div-over-another-div). +Overlay element should have exactly the same size/position as grpah container. +In this demo we are using absolute position for `.graph-overlay` and explicitly +positioned common parent (`body`). See more details here: +[How to overlay one div over another div](http://stackoverflow.com/questions/2941189/how-to-overlay-one-div-over-another-div). -After this is done we are using vivagraph methods to track drag'n'drop actions, and convert [client coordinates into graph coordinates](https://github.com/anvaka/VivaGraphJS/blob/8342dfb9d41fb619ec2e3a505beb508ce7743873/demos/other/webgl-area-select/index.js#L32-L40). +After this is done we are using vivagraph methods to track drag'n'drop actions, +and convert [client coordinates into graph coordinates](https://github.com/anvaka/VivaGraphJS/blob/8342dfb9d41fb619ec2e3a505beb508ce7743873/demos/other/webgl-area-select/index.js#L32-L40). -Finally we are doing linear iteration over all nodes within graph and ask layout to provide their coordinates. If those coordinates are [within bounding rectangle](https://github.com/anvaka/VivaGraphJS/blob/8342dfb9d41fb619ec2e3a505beb508ce7743873/demos/other/webgl-area-select/index.js#L58-L62), we higlight the node. +Finally we are doing linear iteration over all nodes within graph and ask layout +to provide their coordinates. If those coordinates are [within bounding rectangle](https://github.com/anvaka/VivaGraphJS/blob/8342dfb9d41fb619ec2e3a505beb508ce7743873/demos/other/webgl-area-select/index.js#L58-L62), +we higlight the node. From cfa19659e5d20c4fc4fc2d91d45e01f9e09754ae Mon Sep 17 00:00:00 2001 From: anvaka Date: Tue, 24 Mar 2015 22:17:25 -0700 Subject: [PATCH 181/276] Properly handling individual input overrides --- demos/other/input-override/README.md | 80 +++++++++++++++++++++++++++ demos/other/input-override/index.html | 16 ++++++ demos/other/input-override/index.js | 54 ++++++++++++++++++ demos/other/input-override/style.css | 25 +++++++++ src/View/renderer.js | 25 ++++++--- 5 files changed, 193 insertions(+), 7 deletions(-) create mode 100644 demos/other/input-override/README.md create mode 100644 demos/other/input-override/index.html create mode 100644 demos/other/input-override/index.js create mode 100644 demos/other/input-override/style.css diff --git a/demos/other/input-override/README.md b/demos/other/input-override/README.md new file mode 100644 index 0000000..c8eea32 --- /dev/null +++ b/demos/other/input-override/README.md @@ -0,0 +1,80 @@ +# no interaction + +This demo shows how to disable automatic processing of user input by VivaGraph. +For example, if you want to just render a graph, and let users scroll your page +this is the right place to start from. + + +# How? + +When you create a renderer you can explicitly allow or forbid vivagraph to handle +user interaction. By default VivaGraph will allows user to: + +* Zoom in/zoom out using scroll event; +* Drag individual nodes with left mouse; +* Drag entire graph by dragging background canvas. + +To disable all interactions use: + +``` js +Viva.Graph.View.renderer(graph, { + interactive: false +}); +``` + +`intractive` argument can accept either boolean or string type. Boolean is a +global switch for all features. String allows you fine control over features +that you'd like to keep, and can accept any combination of the following words: + +* `node` - enable node interaction +* `drag` - enable background dragging +* `scroll` - enable scrolling + +If you pass a string with just one word it will automatically disable remaining +features. For example, the following code will allow node dragging, but will +forbid vivagraph from controlling scroll-zoom, and canvas dragging: + +``` js +Viva.Graph.View.renderer(graph, { + interactive: 'node' +}); +``` + +To allow bot node dragging and canvas dragging: + +``` js +Viva.Graph.View.renderer(graph, { + interactive: 'node drag' // scroll is disabled! +}); +``` + +To allow only scroll-zoom, but disable the rest, use: + +``` js +Viva.Graph.View.renderer(graph, { + interactive: 'scroll' +}); +``` + +Finally, to explicitly enable all interactions: + +``` js +Viva.Graph.View.renderer(graph, { + interactive: 'scroll drag node' // order of words does not matter +}); +``` + +This is equivalent to: + +``` js +Viva.Graph.View.renderer(graph, { + interactive: true +}); + +// or even shorter, since renderer interactive by default: +Viva.Graph.View.renderer(graph); +``` + +## Default - Viva +``` js +``` diff --git a/demos/other/input-override/index.html b/demos/other/input-override/index.html new file mode 100644 index 0000000..2ff917b --- /dev/null +++ b/demos/other/input-override/index.html @@ -0,0 +1,16 @@ + + + + No interaction - VivaGraph + + + +

+ VivaGraph is allowed to process interaction with individual nodes only. It + will not handle scroll events in this example. +

+ + + + + diff --git a/demos/other/input-override/index.js b/demos/other/input-override/index.js new file mode 100644 index 0000000..fc3d8d3 --- /dev/null +++ b/demos/other/input-override/index.js @@ -0,0 +1,54 @@ +// let's just rend all possible graphs on this page: +var generator = Viva.Graph.generator(); +var graphNames = Object.keys(generator); + +for (var i = 0; i < graphNames.length; ++i) { + renderGraph(graphNames[i]); +} + +function renderGraph(name) { + var graph = generateGraphByName(name); + var layout = Viva.Graph.Layout.forceDirected(graph, { + springLength: 30, + springCoeff: 0.0008, + dragCoeff: 0.01, + gravity: -1.2, + theta: 1 + }); + + var graphics = Viva.Graph.View.webglGraphics(); + var renderer = Viva.Graph.View.renderer(graph, { + // This prevents vivagraph from handling scrolling, but will let user interact + // with individual nodes: + interactive: 'nodes', + // if you want to completely disable interaction, set `interactive` to false. + // interactive: false, + layout: layout, + graphics: graphics, + container: createContainer() + }); + + renderer.run(); +} + +function createContainer() { + var container = document.createElement('div'); + container.className = 'graph-container'; + document.body.appendChild(container); + return container; +} + +// you can safely ignore this function for the purpose of this demo. It just +// generates a random graph an duses custom nodes/links count based on generator +// name. +function generateGraphByName(name) { + if (name === 'wattsStrogatz') { + // wattsStrogatz has different default arguments, let's respect it: + return generator.wattsStrogatz(20, 4, 0.02); + } else if (name === 'completeBipartite') { + // it's more stable this way: + return generator.completeBipartite(3, 3); + } + return generator[name](5, 5, 5); +} + diff --git a/demos/other/input-override/style.css b/demos/other/input-override/style.css new file mode 100644 index 0000000..21b1521 --- /dev/null +++ b/demos/other/input-override/style.css @@ -0,0 +1,25 @@ +body, +html { + width: 100%; + height: 100%; + margin: 0; + padding: 0; + background: black; +} +.graph-container { + width: 480px; + height: 640px; + margin: 0 auto; + border: 1px solid gray; +} +#message { + color: deepskyblue; + font-size: 24px; + position: absolute; + max-width: 320px; + display: block; + font-family: monospace; + color: #999; + top: 10px; + left: 10px; +} diff --git a/src/View/renderer.js b/src/View/renderer.js index 7566c4a..5f1aa90 100644 --- a/src/View/renderer.js +++ b/src/View/renderer.js @@ -190,12 +190,12 @@ function renderer(graph, settings) { }, listenNodeEvents = function (node) { - var wasPinned = false; - var nodeInteractive = (typeof interactive === 'string' && interactive.indexOf('node') !== -1) || interactive; - if (!nodeInteractive) { + if (!isInteractive('node')) { return; } + var wasPinned = false; + // TODO: This may not be memory efficient. Consider reusing handlers object. inputManager.bindDragNDrop(node, { onStart : function () { @@ -325,8 +325,7 @@ function renderer(graph, settings) { windowEvents.on('resize', onWindowResized); releaseContainerDragManager(); - var canDrag = (typeof interactive === 'string' && interactive.indexOf('drag') !== -1) || interactive; - if (canDrag) { + if (isInteractive('drag')) { containerDrag = dragndrop(container); containerDrag.onDrag(function (e, offset) { viewPortOffset.x += offset.x; @@ -337,8 +336,7 @@ function renderer(graph, settings) { }); } - var canScroll = (typeof interactive === 'string' && interactive.indexOf('scroll') !== -1) || interactive; - if (canScroll) { + if (isInteractive('scroll')) { containerDrag.onScroll(function (e, scaleOffset, scrollPoint) { scale(scaleOffset < 0, scrollPoint); }); @@ -460,4 +458,17 @@ function renderer(graph, settings) { return this; } }; + + /** + * Checks whether given interaction (node/scroll) is enabled + */ + function isInteractive(interactionName) { + if (typeof interactive === 'string') { + return interactive.indexOf(interactionName) >= 0; + } else if (typeof interactive === 'boolean') { + return interactive; + } + return true; // default setting + } } + From 3eecb25e82b857dd50de8bdc7c0fdba9600e6dc5 Mon Sep 17 00:00:00 2001 From: anvaka Date: Tue, 24 Mar 2015 22:18:42 -0700 Subject: [PATCH 182/276] Added link to online demo --- demos/other/input-override/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/demos/other/input-override/README.md b/demos/other/input-override/README.md index c8eea32..b1112cb 100644 --- a/demos/other/input-override/README.md +++ b/demos/other/input-override/README.md @@ -4,6 +4,7 @@ This demo shows how to disable automatic processing of user input by VivaGraph. For example, if you want to just render a graph, and let users scroll your page this is the right place to start from. +[See online demo](http://anvaka.github.io/VivaGraphJS/demos/other/input-override/) # How? From 3ee64d6d55749396489f1bc0245b842a4a9243f0 Mon Sep 17 00:00:00 2001 From: anvaka Date: Tue, 24 Mar 2015 22:25:33 -0700 Subject: [PATCH 183/276] 0.7.7 - Minor fixes, latest ngraph --- CHANGELOG | 6 ++- dist/vivagraph.js | 122 ++++++++++++++++++++++++++++-------------- dist/vivagraph.min.js | 4 +- src/version.js | 2 +- 4 files changed, 90 insertions(+), 44 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 989bc73..e08f98c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,9 @@ +v0.7.7 + date Mar 24, 2015 + - Upgraded to latest `ngraph` modules + - Bug fixes v0.7.0 - date Feb 4, 2014 + date Feb 4, 2015 - All files are now CommonJS Modules - `Viva.Graph.svg` is replaced with npm module `simplesvg` - `Viva.Graph.graph` is replaced with `ngraph.graph` diff --git a/dist/vivagraph.js b/dist/vivagraph.js index de83936..e9a6e51 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -2203,12 +2203,22 @@ module.exports = createGraph; var eventify = require('ngraph.events'); -function createGraph() { +/** + * Creates a new graph + */ +function createGraph(options) { // Graph structure is maintained as dictionary of nodes // and array of links. Each node has 'links' property which // hold all links related to that node. And general links // array is used to speed up all links enumeration. This is inefficient // in terms of memory, but simplifies coding. + options = options || {}; + if (options.uniqueLinkId === undefined) { + // Request each link id to be unique between same nodes. This negatively + // impacts `addLink()` performance (O(n), where n - number of edges of each + // vertex), but makes operations with multigraphs more accessible. + options.uniqueLinkId = true; + } var nodes = typeof Object.create === 'function' ? Object.create(null) : {}, links = [], @@ -2218,7 +2228,7 @@ function createGraph() { suspendEvents = 0, forEachNode = createNodeIterator(), - linkConnectionSymbol = '👉 ', + createLink = options.uniqueLinkId ? createUniqueLink : createSingleLink, // Our graph API provides means to listen to graph changes. Users can subscribe // to be notified about changes in the graph by using `on` method. However @@ -2244,7 +2254,7 @@ function createGraph() { * its data is extended with whatever comes in 'data' argument. * * @param nodeId the node's identifier. A string or number is preferred. - * note: Node id should not contain 'linkConnectionSymbol'. This will break link identifiers + * note: Node id should not contain ''. This will break link identifiers * @param [data] additional data for the node being added. If node already * exists its data object is augmented with the new one. * @@ -2440,7 +2450,7 @@ function createGraph() { var node = getNode(nodeId); if (!node) { - // TODO: Should I check for linkConnectionSymbol here? + // TODO: Should I check for 👉 here? node = new Node(nodeId); nodesCount++; recordNodeChange(node, 'add'); @@ -2490,16 +2500,7 @@ function createGraph() { var fromNode = getNode(fromId) || addNode(fromId); var toNode = getNode(toId) || addNode(toId); - var linkId = fromId.toString() + linkConnectionSymbol + toId.toString(); - var isMultiEdge = multiEdges.hasOwnProperty(linkId); - if (isMultiEdge || getLink(fromId, toId)) { - if (!isMultiEdge) { - multiEdges[linkId] = 0; - } - linkId += '@' + (++multiEdges[linkId]); - } - - var link = new Link(fromId, toId, data, linkId); + var link = createLink(fromId, toId, data); links.push(link); @@ -2517,6 +2518,24 @@ function createGraph() { return link; } + function createSingleLink(fromId, toId, data) { + var linkId = fromId.toString() + toId.toString(); + return new Link(fromId, toId, data, linkId); + } + + function createUniqueLink(fromId, toId, data) { + var linkId = fromId.toString() + '👉 ' + toId.toString(); + var isMultiEdge = multiEdges.hasOwnProperty(linkId); + if (isMultiEdge || getLink(fromId, toId)) { + if (!isMultiEdge) { + multiEdges[linkId] = 0; + } + linkId += '@' + (++multiEdges[linkId]); + } + + return new Link(fromId, toId, data, linkId); + } + function getLinks(nodeId) { var node = getNode(nodeId); return node ? node.links : null; @@ -2560,7 +2579,7 @@ function createGraph() { } function getLink(fromNodeId, toNodeId) { - // TODO: Use adjacency matrix to speed up this operation. + // TODO: Use sorted links to speed this up var node = getNode(fromNodeId), i; if (!node) { @@ -2595,26 +2614,38 @@ function createGraph() { } function forEachLinkedNode(nodeId, callback, oriented) { - var node = getNode(nodeId), - i, - link, - linkedNodeId; + var node = getNode(nodeId); if (node && node.links && typeof callback === 'function') { - // Extracted orientation check out of the loop to increase performance if (oriented) { - for (i = 0; i < node.links.length; ++i) { - link = node.links[i]; - if (link.fromId === nodeId) { - callback(nodes[link.toId], link); - } - } + return forEachOrientedLink(node.links, nodeId, callback); } else { - for (i = 0; i < node.links.length; ++i) { - link = node.links[i]; - linkedNodeId = link.fromId === nodeId ? link.toId : link.fromId; + return forEachNonOrientedLink(node.links, nodeId, callback); + } + } + } - callback(nodes[linkedNodeId], link); + function forEachNonOrientedLink(links, nodeId, callback) { + var quitFast; + for (var i = 0; i < links.length; ++i) { + var link = links[i]; + var linkedNodeId = link.fromId === nodeId ? link.toId : link.fromId; + + quitFast = callback(nodes[linkedNodeId], link); + if (quitFast) { + return true; // Client does not need more iterations. Break now. + } + } + } + + function forEachOrientedLink(links, nodeId, callback) { + var quitFast; + for (var i = 0; i < links.length; ++i) { + var link = links[i]; + if (link.fromId === nodeId) { + quitFast = callback(nodes[link.toId], link); + if (quitFast) { + return true; // Client does not need more iterations. Break now. } } } @@ -2652,7 +2683,7 @@ function createGraph() { var keys = Object.keys(nodes); for (var i = 0; i < keys.length; ++i) { if (callback(nodes[keys[i]])) { - return; // client doesn't want to proceed. Return. + return true; // client doesn't want to proceed. Return. } } } @@ -2665,7 +2696,7 @@ function createGraph() { for (node in nodes) { if (callback(nodes[node])) { - return; // client doesn't want to proceed. Return. + return true; // client doesn't want to proceed. Return. } } } @@ -4350,12 +4381,12 @@ function renderer(graph, settings) { }, listenNodeEvents = function (node) { - var wasPinned = false; - var nodeInteractive = (typeof interactive === 'string' && interactive.indexOf('node') !== -1) || interactive; - if (!nodeInteractive) { + if (!isInteractive('node')) { return; } + var wasPinned = false; + // TODO: This may not be memory efficient. Consider reusing handlers object. inputManager.bindDragNDrop(node, { onStart : function () { @@ -4485,8 +4516,7 @@ function renderer(graph, settings) { windowEvents.on('resize', onWindowResized); releaseContainerDragManager(); - var canDrag = (typeof interactive === 'string' && interactive.indexOf('drag') !== -1) || interactive; - if (canDrag) { + if (isInteractive('drag')) { containerDrag = dragndrop(container); containerDrag.onDrag(function (e, offset) { viewPortOffset.x += offset.x; @@ -4497,8 +4527,7 @@ function renderer(graph, settings) { }); } - var canScroll = (typeof interactive === 'string' && interactive.indexOf('scroll') !== -1) || interactive; - if (canScroll) { + if (isInteractive('scroll')) { containerDrag.onScroll(function (e, scaleOffset, scrollPoint) { scale(scaleOffset < 0, scrollPoint); }); @@ -4620,7 +4649,20 @@ function renderer(graph, settings) { return this; } }; + + /** + * Checks whether given interaction (node/scroll) is enabled + */ + function isInteractive(interactionName) { + if (typeof interactive === 'string') { + return interactive.indexOf(interactionName) >= 0; + } else if (typeof interactive === 'boolean') { + return interactive; + } + return true; // default setting + } } + },{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.forcelayout":7,"ngraph.graph":24}],50:[function(require,module,exports){ /** @@ -6802,7 +6844,7 @@ function webglSquare(size, color) { },{"./parseColor.js":52}],63:[function(require,module,exports){ // todo: this should be generated at build time. -module.exports = '0.7.6'; +module.exports = '0.7.7'; },{}]},{},[1])(1) }); \ No newline at end of file diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 2ac90a8..13ba7ba 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-s*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=t},{}],3:[function(e,n){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n){function t(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function g(e){var n=w[e];n.mass=y(e)}function h(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function m(e){var n=w[e];return n||(c(e),n=w[e]),n}function y(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var x=e("ngraph.physics.simulator");t=t||x(),o(t,"physicsSimulator").has("step","getBestNewBodyPosition","addBodyAt");var w="function"==typeof Object.create?Object.create(null):{},b={},E=t.settings.springTransform||r;f(),u();var L={step:function(){return t.step()},getNodePosition:function(e){return m(e).pos},setNodePosition:function(e){var n=m(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return t.getBBox()},pinNode:function(e,n){var t=m(e.id);t.isPinned=!!n},isNodePinned:function(e){return m(e.id).isPinned},dispose:function(){n.off("changed",s)},getBody:a,getSpring:i,simulator:t};return L}function r(){}n.exports=t,n.exports.simulator=e("ngraph.physics.simulator");var o=e("varta")},{"ngraph.physics.simulator":8,varta:21}],8:[function(e,n){function t(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.force.reset(),v.updateBodyForce(e),m.update(e);for(n=p.length;n--;)h.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),u=n.createBounds||e("./lib/bounds"),s=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),g=u(l,n),h=f(n),m=s(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return g.update(),en))return l.splice(n,1),0===l.length&&g.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return g.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=t},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":25,"ngraph.quadtreebh":17}],9:[function(e,n){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;ut;++t){var s=e[t],f=n/s.mass;s.velocity.x+=f*s.force.x,s.velocity.y+=f*s.force.y;var c=s.velocity.x,d=s.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=t},{}],13:[function(e,n){function t(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=t},{}],14:[function(e,n){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":25,"ngraph.random":26}],15:[function(e,n){function t(e,n,t){var o="[object Array]"===Object.prototype.toString.call(t);if(o)for(var i=0;i0&&u(s.pos,a.pos));if(0===f&&u(s.pos,a.pos))return}c.push(i,s),c.push(i,a)}else{var h=a.pos.x,m=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*h,i.massY=i.massY+a.mass*m;var y=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;if(h>w){y+=1;var L=x;x=w,w+=w-L}if(m>E){y+=2;var P=b;b=E,E+=E-P}var N=t(i,y);N?c.push(N,a):(N=v(),N.left=x,N.top=b,N.right=w,N.bottom=E,N.body=a,r(i,y,N))}}},m=function(e){var n,t,r,i,a=f,u=0,c=0,l=1,p=0,v=1;for(a[0]=g;l;){var h=a[p],m=h.body;l-=1,p+=1;var y=m!==e;m&&y?(t=m.pos.x-e.pos.x,r=m.pos.y-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),n=s*m.mass*e.mass/(i*i*i),u+=n*t,c+=n*r):y&&(t=h.massX/h.mass-e.pos.x,r=h.massY/h.mass-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),(h.right-h.left)/iu&&(t=u),u>o&&(o=u),r>s&&(r=s),s>i&&(i=s)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,p=0,g=v(),g.left=t,g.right=o,g.top=r,g.bottom=i,n=a-1,n>0&&(g.body=e[n]);n--;)h(e[n],g)};return{insertBodies:y,updateBodyForce:m,options:function(e){return e?("number"==typeof e.gravity&&(s=e.gravity),"number"==typeof e.theta&&(d=e.theta),this):{gravity:s,theta:d}}}}},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":26}],18:[function(e,n){function t(){this.stack=[],this.popIdx=0}function r(e,n){this.node=e,this.body=n}n.exports=t,t.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new r(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],19:[function(e,n){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],20:[function(e,n){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],21:[function(e,n){function t(e,n){function t(){return o(e,n,arguments)}return n=n||"Argument",{has:t}}function r(){function e(e,t){return o(e,t,n)}var n=arguments;return e}function o(e,n,t){if(void 0===e)throw new Error(n+" is not defined");for(var r=0;re)throw new Error("Invalid number of nodes");var n,t=l();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function r(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=t(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function o(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=l();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function i(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=l();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function a(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=l();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function u(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=l();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function s(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=l();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var u=i*e*n,s=r+o*e+u;r>0&&a.addLink(s,r-1+o*e+u),o>0&&a.addLink(s,r+(o-1)*e+u),i>0&&a.addLink(s,r+o*e+(i-1)*e*n)}return a}function f(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=l(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function c(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=l();for(n=0;e>n;++n)t.addNode(n);return t}function d(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,u=e("ngraph.random").random(o||42),s=l();for(i=0;n>i;++i)s.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,s.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(u.nextDouble()n)return!1;S(),P.splice(n,1);var t=s(e.fromId),o=s(e.toId);return t&&(n=r(e,t.links),n>=0&&t.links.splice(n,1)),o&&(n=r(e,o.links),n>=0&&o.links.splice(n,1)),T(e,"remove"),D(),!0}function p(e,n){var t,r=s(e);if(!r)return null;for(t=0;tn;++n)e(P[n])}function h(e,n,t){var r,o,i,a=s(e);if(a&&a.links&&"function"==typeof n)if(t)for(r=0;r0&&(M.fire("changed",I),I.length=0)}function w(){return Object.keys?b:E}function b(e){if("function"==typeof e)for(var n=Object.keys(L),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function o(e){this.id=e,this.links=[],this.data=null}function i(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=t;var a=e("ngraph.events")},{"ngraph.events":6}],25:[function(e,n){function t(e,n){var r;if(e||(e={}),n)for(r in n)if(n.hasOwnProperty(r)){var o=e.hasOwnProperty(r),i=typeof n[r],a=!o||typeof e[r]!==i;a?e[r]=n[r]:"object"===i&&(e[r]=t(e[r],n[r]))}return e}n.exports=t},{}],26:[function(e,n){function t(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function r(e,n){var r=n||t();if("function"!=typeof r.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var t,o,i;for(t=e.length-1;t>0;--t)o=r.next(t+1),i=e[o],e[o]=e[t],e[t]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,t,o;for(n=e.length-1;n>0;--n)t=r.next(n+1),o=e[t],e[t]=e[n],e[n]=o;return e}}}n.exports={random:t,randomIterator:r}},{}],27:[function(e,n){function t(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=t},{}],28:[function(e,n){function t(e,n){var t=r(e);if(void 0===n)return t;for(var o=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},k=function(e){p=!1,r.off("touchmove",A),r.off("touchend",k),r.off("touchcancel",k),c=null,a&&a(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,r.on("touchmove",A),r.on("touchend",k),r.on("touchcancel",k))},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this -},onStop:function(e){return a=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),r.off("mousemove",w),r.off("mouseup",E),r.off("touchmove",A),r.off("touchend",k),r.off("touchcancel",k),P(null)}}}n.exports=t;var r=e("../Utils/documentEvents.js"),o=e("../Utils/browserInfo.js"),i=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":40,"../Utils/documentEvents.js":41,"../Utils/findElementPosition.js":42}],37:[function(e,n){function t(e,n){var t=r(n),o=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){o=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(o);var r=i[e.id];return r&&r.onStart&&r.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(o),o=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(o){var t=i[o.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=t;var r=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":58}],38:[function(e,n){function t(e,n){function t(e){return d[e]}n=r(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var a=o(n.seed),u=new i(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(){return{x:a.next(n.maxX),y:a.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n0)for(e=0;en,t)}),e.forEachNode(O),H(),e.on("changed",X)},K=function(){y=!1,H(),W(),a.off("resize",V),j.off(),l.stop(),e.forEachLink(function(e){n.renderLinks&&B(e)}),e.forEachNode(function(e){F(e),U(e)}),v.dispose(),z()};return{run:function(e){return y||(k(),S(),D(),G(),$(),y=!0),T(e),this},reset:function(){g.resetScale(),D(),A.scale=1},pause:function(){P=!0,l.stop()},resume:function(){P=!1,l.restart()},rerender:function(){return _(),this},zoomOut:function(){return J(!0)},zoomIn:function(){return J(!1)},moveTo:function(e,n){g.graphCenterChanged(A.offsetX-e*A.scale,A.offsetY-n*A.scale),_()},getGraphics:function(){return g},dispose:function(){K()},on:function(e,n){return j.addEventListener(e,n),this},off:function(e,n){return j.removeEventListener(e,n),this}}}n.exports=t;var r=e("ngraph.graph"),o=e("ngraph.forcelayout"),i=e("./svgGraphics.js"),a=e("../Utils/windowEvents.js"),u=e("../Input/domInputManager.js"),s=e("../Utils/timer.js"),f=e("../Utils/getDimensions.js"),c=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.forcelayout":7,"ngraph.graph":24}],50:[function(e,n){function t(){function e(){var e=r("svg");return n=r("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,a,u,s,f=1,c={},d={},l=function(){return r("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(){return r("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+a+","+u+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){a=e,u=n,w()},inputManager:i,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),s=n.getCTM().multiply(i);f=s.a,a=s.e,u=s.f;var c="matrix("+s.a+", 0, 0,"+s.d+","+s.e+","+s.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof s&&s(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):s=e),t},getSvgRoot:function(){return t}};return o(b),b}n.exports=t;var r=e("simplesvg"),o=e("ngraph.events"),i=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":35,"ngraph.events":6,simplesvg:28}],51:[function(e,n){function t(e){e=f(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,c,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=o(),P=i(),N=function(){return a()},A=function(){return u(3014898687)},k=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),c&&c.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(A=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:r,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,k()},addLink:function(e,n){var t=m++,r=A(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],k()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,k(),I(this),y[0]},resetScale:function(){return j(),c&&(_(),k()),this},init:function(r){var o={};if(e.preserveDrawingBuffer&&(o.preserveDrawingBuffer=!0),n=r,_(),j(),n.appendChild(t),c=t.getContext("experimental-webgl",o),!c){var i="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(i),i}if(e.enableBlending&&(c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA),c.enable(c.BLEND)),e.clearColor){var a=e.clearColorValue;c.clearColor(a.r,a.g,a.b,a.a),this.beginRender=function(){c.clear(c.COLOR_BUFFER_BIT)}}L.load(c),L.updateSize(d/2,l/2),P.load(c),P.updateSize(d/2,l/2),k(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!c&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!c&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return s(T),T}n.exports=t;var r=e("../Input/webglInputManager.js"),o=e("../WebGL/webglLinkProgram.js"),i=e("../WebGL/webglNodeProgram.js"),a=e("../WebGL/webglSquare.js"),u=e("../WebGL/webglLine.js"),s=e("ngraph.events"),f=e("ngraph.merge")},{"../Input/webglInputManager.js":37,"../WebGL/webglLine.js":59,"../WebGL/webglLinkProgram.js":60,"../WebGL/webglNodeProgram.js":61,"../WebGL/webglSquare.js":62,"ngraph.events":6,"ngraph.merge":25}],52:[function(e,n){function t(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=t},{}],53:[function(e,n){function t(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=t},{}],54:[function(e,n){function t(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function i(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function o(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=t},{}],55:[function(e,n){function t(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!r(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:i,getCoordinates:a,load:u};return E}function r(e){return 0===(e&e-1)}var o=e("./texture.js");n.exports=t},{"./texture.js":53}],56:[function(e,n){function t(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=t},{}],57:[function(e,n){function t(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=r(),A=o(),k=1024,j=0,_=new Float32Array(64);return{load:t,position:u,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function r(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function o(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var i=e("./webglAtlas.js"),a=e("./webgl.js");n.exports=t},{"./webgl.js":54,"./webglAtlas.js":55}],58:[function(e,n){function t(e){function n(){x=null}function t(e){x=e}function o(e){return"function"==typeof e&&A.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(A,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],A=[],k=e.getGraphicsRoot();h(k);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:o,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var r=e("../Utils/documentEvents.js");n.exports=t},{"../Utils/documentEvents.js":41}],59:[function(e,n){function t(e){return{color:r(e)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],60:[function(e,n){function t(){var e,n,t,o,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,o=r(a),e=o.createProgram(v,p),n.useProgram(e),i=o.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&o.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&o.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],61:[function(e,n){function t(){function e(){if((A+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=r(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function o(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){A>0&&(A-=1),e.id0&&v.copyArrayPart(N,e.id*x,A*x,x)}function u(){e(),A+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,A)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),A=0;return{load:n,position:t,updateTransform:o,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],62:[function(e,n){function t(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],63:[function(e,n){n.exports="0.7.6"},{}]},{},[1])(1)}); \ No newline at end of file +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-s*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=t},{}],3:[function(e,n){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n){function t(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function g(e){var n=w[e];n.mass=y(e)}function h(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function m(e){var n=w[e];return n||(c(e),n=w[e]),n}function y(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var x=e("ngraph.physics.simulator");t=t||x(),o(t,"physicsSimulator").has("step","getBestNewBodyPosition","addBodyAt");var w="function"==typeof Object.create?Object.create(null):{},b={},E=t.settings.springTransform||r;f(),u();var L={step:function(){return t.step()},getNodePosition:function(e){return m(e).pos},setNodePosition:function(e){var n=m(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return t.getBBox()},pinNode:function(e,n){var t=m(e.id);t.isPinned=!!n},isNodePinned:function(e){return m(e.id).isPinned},dispose:function(){n.off("changed",s)},getBody:a,getSpring:i,simulator:t};return L}function r(){}n.exports=t,n.exports.simulator=e("ngraph.physics.simulator");var o=e("varta")},{"ngraph.physics.simulator":8,varta:21}],8:[function(e,n){function t(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.force.reset(),v.updateBodyForce(e),m.update(e);for(n=p.length;n--;)h.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),u=n.createBounds||e("./lib/bounds"),s=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),g=u(l,n),h=f(n),m=s(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return g.update(),en))return l.splice(n,1),0===l.length&&g.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return g.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=t},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":25,"ngraph.quadtreebh":17}],9:[function(e,n){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;ut;++t){var s=e[t],f=n/s.mass;s.velocity.x+=f*s.force.x,s.velocity.y+=f*s.force.y;var c=s.velocity.x,d=s.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=t},{}],13:[function(e,n){function t(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=t},{}],14:[function(e,n){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":25,"ngraph.random":26}],15:[function(e,n){function t(e,n,t){var o="[object Array]"===Object.prototype.toString.call(t);if(o)for(var i=0;i0&&u(s.pos,a.pos));if(0===f&&u(s.pos,a.pos))return}c.push(i,s),c.push(i,a)}else{var h=a.pos.x,m=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*h,i.massY=i.massY+a.mass*m;var y=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;if(h>w){y+=1;var L=x;x=w,w+=w-L}if(m>E){y+=2;var P=b;b=E,E+=E-P}var N=t(i,y);N?c.push(N,a):(N=v(),N.left=x,N.top=b,N.right=w,N.bottom=E,N.body=a,r(i,y,N))}}},m=function(e){var n,t,r,i,a=f,u=0,c=0,l=1,p=0,v=1;for(a[0]=g;l;){var h=a[p],m=h.body;l-=1,p+=1;var y=m!==e;m&&y?(t=m.pos.x-e.pos.x,r=m.pos.y-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),n=s*m.mass*e.mass/(i*i*i),u+=n*t,c+=n*r):y&&(t=h.massX/h.mass-e.pos.x,r=h.massY/h.mass-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),(h.right-h.left)/iu&&(t=u),u>o&&(o=u),r>s&&(r=s),s>i&&(i=s)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,p=0,g=v(),g.left=t,g.right=o,g.top=r,g.bottom=i,n=a-1,n>0&&(g.body=e[n]);n--;)h(e[n],g)};return{insertBodies:y,updateBodyForce:m,options:function(e){return e?("number"==typeof e.gravity&&(s=e.gravity),"number"==typeof e.theta&&(d=e.theta),this):{gravity:s,theta:d}}}}},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":26}],18:[function(e,n){function t(){this.stack=[],this.popIdx=0}function r(e,n){this.node=e,this.body=n}n.exports=t,t.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new r(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],19:[function(e,n){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],20:[function(e,n){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],21:[function(e,n){function t(e,n){function t(){return o(e,n,arguments)}return n=n||"Argument",{has:t}}function r(){function e(e,t){return o(e,t,n)}var n=arguments;return e}function o(e,n,t){if(void 0===e)throw new Error(n+" is not defined");for(var r=0;re)throw new Error("Invalid number of nodes");var n,t=l();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function r(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=t(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function o(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=l();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function i(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=l();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function a(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=l();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function u(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=l();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function s(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=l();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var u=i*e*n,s=r+o*e+u;r>0&&a.addLink(s,r-1+o*e+u),o>0&&a.addLink(s,r+(o-1)*e+u),i>0&&a.addLink(s,r+o*e+(i-1)*e*n)}return a}function f(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=l(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function c(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=l();for(n=0;e>n;++n)t.addNode(n);return t}function d(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,u=e("ngraph.random").random(o||42),s=l();for(i=0;n>i;++i)s.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,s.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(u.nextDouble()n)return!1;B(),_.splice(n,1);var t=f(e.fromId),o=f(e.toId);return t&&(n=r(e,t.links),n>=0&&t.links.splice(n,1)),o&&(n=r(e,o.links),n>=0&&o.links.splice(n,1)),U(e,"remove"),F(),!0}function h(e,n){var t,r=f(e);if(!r)return null;for(t=0;tn;++n)e(_[n])}function x(e,n,t){var r=f(e);return r&&r.links&&"function"==typeof n?t?b(r.links,e,n):w(r.links,e,n):void 0}function w(e,n,t){for(var r,o=0;o0&&(O.fire("changed",M),M.length=0)}function N(){return Object.keys?k:A}function k(e){if("function"==typeof e)for(var n=Object.keys(j),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function o(e){this.id=e,this.links=[],this.data=null}function i(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=t;var a=e("ngraph.events")},{"ngraph.events":6}],25:[function(e,n){function t(e,n){var r;if(e||(e={}),n)for(r in n)if(n.hasOwnProperty(r)){var o=e.hasOwnProperty(r),i=typeof n[r],a=!o||typeof e[r]!==i;a?e[r]=n[r]:"object"===i&&(e[r]=t(e[r],n[r]))}return e}n.exports=t},{}],26:[function(e,n){function t(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function r(e,n){var r=n||t();if("function"!=typeof r.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var t,o,i;for(t=e.length-1;t>0;--t)o=r.next(t+1),i=e[o],e[o]=e[t],e[t]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,t,o;for(n=e.length-1;n>0;--n)t=r.next(n+1),o=e[t],e[t]=e[n],e[n]=o;return e}}}n.exports={random:t,randomIterator:r}},{}],27:[function(e,n){function t(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=t},{}],28:[function(e,n){function t(e,n){var t=r(e);if(void 0===n)return t;for(var o=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},A=function(e){p=!1,r.off("touchmove",k),r.off("touchend",A),r.off("touchcancel",A),c=null,a&&a(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,r.on("touchmove",k),r.on("touchend",A),r.on("touchcancel",A)) +},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return a=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),r.off("mousemove",w),r.off("mouseup",E),r.off("touchmove",k),r.off("touchend",A),r.off("touchcancel",A),P(null)}}}n.exports=t;var r=e("../Utils/documentEvents.js"),o=e("../Utils/browserInfo.js"),i=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":40,"../Utils/documentEvents.js":41,"../Utils/findElementPosition.js":42}],37:[function(e,n){function t(e,n){var t=r(n),o=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){o=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(o);var r=i[e.id];return r&&r.onStart&&r.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(o),o=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(o){var t=i[o.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=t;var r=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":58}],38:[function(e,n){function t(e,n){function t(e){return d[e]}n=r(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var a=o(n.seed),u=new i(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(){return{x:a.next(n.maxX),y:a.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"==typeof y?y:!0}var d=30;n=n||{};var l,p,v,g=n.layout,h=n.graphics,m=n.container,y=void 0!==n.interactive?n.interactive:!0,x=!1,w=!0,b=0,E=0,L=!1,P=!1,N=!1,k={x:0,y:0},A={offsetX:0,offsetY:0,scale:1},j=function(){m=m||window.document.body,g=g||o(e,o.simulator({springLength:80,springCoeff:2e-4})),h=h||i(e,{container:m}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,l=(h.inputManager||u)(e,h)},_=r({}),I=function(){h.beginRender(),n.renderLinks&&h.renderLinks(),h.renderNodes(),h.endRender()},T=function(){return L=g.step()&&!P,I(),!L},C=function(e){return p?void(E+=e):void(e?(E+=e,p=s(function(){return T()},d)):(b=0,E=0,p=s(T,d)))},S=function(){N||(L=!1,p.restart())},D=function(){var e;if("number"==typeof n.prerender&&n.prerender>0)for(e=0;en,t)}),e.forEachNode(O),J(),e.on("changed",V)},Q=function(){x=!1,J(),H(),a.off("resize",W),_.off(),p.stop(),e.forEachLink(function(e){n.renderLinks&&F(e)}),e.forEachNode(function(e){G(e),R(e)}),g.dispose(),q()};return{run:function(e){return x||(j(),D(),M(),z(),K(),x=!0),C(e),this},reset:function(){h.resetScale(),M(),A.scale=1},pause:function(){N=!0,p.stop()},resume:function(){N=!1,p.restart()},rerender:function(){return I(),this},zoomOut:function(){return $(!0)},zoomIn:function(){return $(!1)},moveTo:function(e,n){h.graphCenterChanged(A.offsetX-e*A.scale,A.offsetY-n*A.scale),I()},getGraphics:function(){return h},dispose:function(){Q()},on:function(e,n){return _.addEventListener(e,n),this},off:function(e,n){return _.removeEventListener(e,n),this}}}n.exports=t;var r=e("ngraph.graph"),o=e("ngraph.forcelayout"),i=e("./svgGraphics.js"),a=e("../Utils/windowEvents.js"),u=e("../Input/domInputManager.js"),s=e("../Utils/timer.js"),f=e("../Utils/getDimensions.js"),c=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.forcelayout":7,"ngraph.graph":24}],50:[function(e,n){function t(){function e(){var e=r("svg");return n=r("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,a,u,s,f=1,c={},d={},l=function(){return r("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(){return r("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+a+","+u+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){a=e,u=n,w()},inputManager:i,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),s=n.getCTM().multiply(i);f=s.a,a=s.e,u=s.f;var c="matrix("+s.a+", 0, 0,"+s.d+","+s.e+","+s.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof s&&s(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):s=e),t},getSvgRoot:function(){return t}};return o(b),b}n.exports=t;var r=e("simplesvg"),o=e("ngraph.events"),i=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":35,"ngraph.events":6,simplesvg:28}],51:[function(e,n){function t(e){e=f(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,c,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=o(),P=i(),N=function(){return a()},k=function(){return u(3014898687)},A=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),c&&c.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(k=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:r,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,A()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],A()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,A(),I(this),y[0]},resetScale:function(){return j(),c&&(_(),A()),this},init:function(r){var o={};if(e.preserveDrawingBuffer&&(o.preserveDrawingBuffer=!0),n=r,_(),j(),n.appendChild(t),c=t.getContext("experimental-webgl",o),!c){var i="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(i),i}if(e.enableBlending&&(c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA),c.enable(c.BLEND)),e.clearColor){var a=e.clearColorValue;c.clearColor(a.r,a.g,a.b,a.a),this.beginRender=function(){c.clear(c.COLOR_BUFFER_BIT)}}L.load(c),L.updateSize(d/2,l/2),P.load(c),P.updateSize(d/2,l/2),A(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!c&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!c&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return s(T),T}n.exports=t;var r=e("../Input/webglInputManager.js"),o=e("../WebGL/webglLinkProgram.js"),i=e("../WebGL/webglNodeProgram.js"),a=e("../WebGL/webglSquare.js"),u=e("../WebGL/webglLine.js"),s=e("ngraph.events"),f=e("ngraph.merge")},{"../Input/webglInputManager.js":37,"../WebGL/webglLine.js":59,"../WebGL/webglLinkProgram.js":60,"../WebGL/webglNodeProgram.js":61,"../WebGL/webglSquare.js":62,"ngraph.events":6,"ngraph.merge":25}],52:[function(e,n){function t(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=t},{}],53:[function(e,n){function t(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=t},{}],54:[function(e,n){function t(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function i(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function o(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=t},{}],55:[function(e,n){function t(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!r(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:i,getCoordinates:a,load:u};return E}function r(e){return 0===(e&e-1)}var o=e("./texture.js");n.exports=t},{"./texture.js":53}],56:[function(e,n){function t(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=t},{}],57:[function(e,n){function t(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=r(),k=o(),A=1024,j=0,_=new Float32Array(64);return{load:t,position:u,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function r(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function o(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var i=e("./webglAtlas.js"),a=e("./webgl.js");n.exports=t},{"./webgl.js":54,"./webglAtlas.js":55}],58:[function(e,n){function t(e){function n(){x=null}function t(e){x=e}function o(e){return"function"==typeof e&&k.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(k,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],k=[],A=e.getGraphicsRoot();h(A);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:o,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var r=e("../Utils/documentEvents.js");n.exports=t},{"../Utils/documentEvents.js":41}],59:[function(e,n){function t(e){return{color:r(e)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],60:[function(e,n){function t(){var e,n,t,o,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,o=r(a),e=o.createProgram(v,p),n.useProgram(e),i=o.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&o.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&o.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],61:[function(e,n){function t(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=r(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function o(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(N,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:o,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],62:[function(e,n){function t(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],63:[function(e,n){n.exports="0.7.7"},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/src/version.js b/src/version.js index 6a8db6d..51d3684 100644 --- a/src/version.js +++ b/src/version.js @@ -1,2 +1,2 @@ // todo: this should be generated at build time. -module.exports = '0.7.6'; +module.exports = '0.7.7'; From 1e520ca3c12312d287e9e18f1605a5ec516c026a Mon Sep 17 00:00:00 2001 From: anvaka Date: Tue, 24 Mar 2015 22:25:51 -0700 Subject: [PATCH 184/276] 0.7.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 10f3c8f..3e70ae5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.7.6", + "version": "0.7.7", "description": "Graph Drawing Library", "main": "src/viva", "directories": { From 0db8aa7cffecc0fa435480d2551d09c3e335ffdb Mon Sep 17 00:00:00 2001 From: anvaka Date: Tue, 24 Mar 2015 22:27:39 -0700 Subject: [PATCH 185/276] Updated README --- demos/other/input-override/README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/demos/other/input-override/README.md b/demos/other/input-override/README.md index b1112cb..a9ac837 100644 --- a/demos/other/input-override/README.md +++ b/demos/other/input-override/README.md @@ -75,7 +75,3 @@ Viva.Graph.View.renderer(graph, { // or even shorter, since renderer interactive by default: Viva.Graph.View.renderer(graph); ``` - -## Default - Viva -``` js -``` From d02df8a734a7eddc5a721277244a12ac8d4e5d11 Mon Sep 17 00:00:00 2001 From: Andrei Kashcha Date: Tue, 24 Mar 2015 22:34:58 -0700 Subject: [PATCH 186/276] Update README.md --- demos/other/input-override/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demos/other/input-override/README.md b/demos/other/input-override/README.md index a9ac837..93700f9 100644 --- a/demos/other/input-override/README.md +++ b/demos/other/input-override/README.md @@ -41,7 +41,7 @@ Viva.Graph.View.renderer(graph, { }); ``` -To allow bot node dragging and canvas dragging: +To allow both node dragging and canvas dragging: ``` js Viva.Graph.View.renderer(graph, { From ad7d481af9d3ec8eeaa0f73351becc5c724981c8 Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 25 Mar 2015 21:47:42 -0700 Subject: [PATCH 187/276] Use formatting consistent with the rest of ngraph --- src/View/renderer.js | 787 ++++++++++++++++++++++--------------------- 1 file changed, 397 insertions(+), 390 deletions(-) diff --git a/src/View/renderer.js b/src/View/renderer.js index 5f1aa90..1a62e05 100644 --- a/src/View/renderer.js +++ b/src/View/renderer.js @@ -52,423 +52,430 @@ var dragndrop = require('../Input/dragndrop.js'); * } */ function renderer(graph, settings) { - // TODO: This class is getting hard to understand. Consider refactoring. - // TODO: I have a technical debt here: fix scaling/recentering! Currently it's a total mess. - var FRAME_INTERVAL = 30; - - settings = settings || {}; - - var layout = settings.layout, - graphics = settings.graphics, - container = settings.container, - interactive = settings.interactive !== undefined ? settings.interactive : true, - inputManager, - animationTimer, - rendererInitialized = false, - updateCenterRequired = true, - - currentStep = 0, - totalIterationsCount = 0, - isStable = false, - userInteraction = false, - isPaused = false, - - viewPortOffset = { - x : 0, - y : 0 - }, - - transform = { - offsetX : 0, - offsetY : 0, - scale : 1 - }; - - var prepareSettings = function () { - container = container || window.document.body; - layout = layout || forceDirected(graph, forceDirected.simulator({ - springLength: 80, - springCoeff: 0.0002, - })); - graphics = graphics || svgGraphics(graph, {container : container}); - - if (!settings.hasOwnProperty('renderLinks')) { - settings.renderLinks = true; - } - - settings.prerender = settings.prerender || 0; - inputManager = (graphics.inputManager || domInputManager)(graph, graphics); - }, - publicEvents = eventify({}), - containerDrag, - - renderGraph = function () { - graphics.beginRender(); - - // todo: move this check graphics - if (settings.renderLinks) { - graphics.renderLinks(); - } - graphics.renderNodes(); - graphics.endRender(); - }, - - onRenderFrame = function () { - isStable = layout.step() && !userInteraction; - renderGraph(); - - return !isStable; - }, - - renderIterations = function (iterationsCount) { - if (animationTimer) { - totalIterationsCount += iterationsCount; - return; - } - - if (iterationsCount) { - totalIterationsCount += iterationsCount; - - animationTimer = timer(function () { - return onRenderFrame(); - }, FRAME_INTERVAL); - } else { - currentStep = 0; - totalIterationsCount = 0; - animationTimer = timer(onRenderFrame, FRAME_INTERVAL); - } - }, - - resetStable = function () { - if(isPaused) { - return; - } - - isStable = false; - animationTimer.restart(); - }, - - prerender = function () { - // To get good initial positions for the graph - // perform several prerender steps in background. - var i; - if (typeof settings.prerender === 'number' && settings.prerender > 0) { - for (i = 0; i < settings.prerender; i += 1) { - layout.step(); - } - } - }, - - updateCenter = function () { - var graphRect = layout.getGraphRect(), - containerSize = getDimension(container); - - viewPortOffset.x = viewPortOffset.y = 0; - transform.offsetX = containerSize.width / 2 - (graphRect.x2 + graphRect.x1) / 2; - transform.offsetY = containerSize.height / 2 - (graphRect.y2 + graphRect.y1) / 2; - graphics.graphCenterChanged(transform.offsetX, transform.offsetY); - - updateCenterRequired = false; - }, - - createNodeUi = function (node) { - var nodePosition = layout.getNodePosition(node.id); - graphics.addNode(node, nodePosition); - }, - - removeNodeUi = function (node) { - graphics.releaseNode(node); - }, - - createLinkUi = function (link) { - var linkPosition = layout.getLinkPosition(link.id); - graphics.addLink(link, linkPosition); - }, - - removeLinkUi = function (link) { - graphics.releaseLink(link); - }, - - listenNodeEvents = function (node) { - if (!isInteractive('node')) { - return; - } - - var wasPinned = false; - - // TODO: This may not be memory efficient. Consider reusing handlers object. - inputManager.bindDragNDrop(node, { - onStart : function () { - wasPinned = layout.isNodePinned(node); - layout.pinNode(node, true); - userInteraction = true; - resetStable(); - }, - onDrag : function (e, offset) { - var oldPos = layout.getNodePosition(node.id); - layout.setNodePosition(node.id, - oldPos.x + offset.x / transform.scale, - oldPos.y + offset.y / transform.scale); - - userInteraction = true; - - renderGraph(); - }, - onStop : function () { - layout.pinNode(node, wasPinned); - userInteraction = false; - } - }); - }, - - releaseNodeEvents = function (node) { - inputManager.bindDragNDrop(node, null); - }, - - initDom = function () { - graphics.init(container); - - graph.forEachNode(createNodeUi); - - if (settings.renderLinks) { - graph.forEachLink(createLinkUi); - } - }, - - releaseDom = function () { - graphics.release(container); - }, - - processNodeChange = function (change) { - var node = change.node; - - if (change.changeType === 'add') { - createNodeUi(node); - listenNodeEvents(node); - if (updateCenterRequired) { - updateCenter(); - } - } else if (change.changeType === 'remove') { - releaseNodeEvents(node); - removeNodeUi(node); - if (graph.getNodesCount() === 0) { - updateCenterRequired = true; // Next time when node is added - center the graph. - } - } else if (change.changeType === 'update') { - releaseNodeEvents(node); - removeNodeUi(node); - - createNodeUi(node); - listenNodeEvents(node); - } - }, - - processLinkChange = function (change) { - var link = change.link; - if (change.changeType === 'add') { - if (settings.renderLinks) { createLinkUi(link); } - } else if (change.changeType === 'remove') { - if (settings.renderLinks) { removeLinkUi(link); } - } else if (change.changeType === 'update') { - throw 'Update type is not implemented. TODO: Implement me!'; - } - }, - - onGraphChanged = function (changes) { - var i, change; - for (i = 0; i < changes.length; i += 1) { - change = changes[i]; - if (change.node) { - processNodeChange(change); - } else if (change.link) { - processLinkChange(change); - } - } - - resetStable(); - }, - - onWindowResized = function () { - updateCenter(); - onRenderFrame(); - }, - - releaseContainerDragManager = function () { - if (containerDrag) { - containerDrag.release(); - containerDrag = null; - } - }, - - releaseGraphEvents = function () { - graph.off('changed', onGraphChanged); - }, + // TODO: This class is getting hard to understand. Consider refactoring. + // TODO: I have a technical debt here: fix scaling/recentering! Currently it's a total mess. + var FRAME_INTERVAL = 30; + + settings = settings || {}; + + var layout = settings.layout, + graphics = settings.graphics, + container = settings.container, + interactive = settings.interactive !== undefined ? settings.interactive : true, + inputManager, + animationTimer, + rendererInitialized = false, + updateCenterRequired = true, + + currentStep = 0, + totalIterationsCount = 0, + isStable = false, + userInteraction = false, + isPaused = false, + + viewPortOffset = { + x: 0, + y: 0 + }, + + transform = { + offsetX: 0, + offsetY: 0, + scale: 1 + }; - scale = function (out, scrollPoint) { - if (!scrollPoint) { - var containerSize = getDimension(container); - scrollPoint = { - x: containerSize.width/2, - y: containerSize.height/2 - }; - } - var scaleFactor = Math.pow(1 + 0.4, out ? -0.2 : 0.2); - transform.scale = graphics.scale(scaleFactor, scrollPoint); - - renderGraph(); - publicEvents.fire('scale', transform.scale); - - return transform.scale; - }, + var prepareSettings = function() { + container = container || window.document.body; + layout = layout || forceDirected(graph, forceDirected.simulator({ + springLength: 80, + springCoeff: 0.0002, + })); + graphics = graphics || svgGraphics(graph, { + container: container + }); + + if (!settings.hasOwnProperty('renderLinks')) { + settings.renderLinks = true; + } + + settings.prerender = settings.prerender || 0; + inputManager = (graphics.inputManager || domInputManager)(graph, graphics); + }, + publicEvents = eventify({}), + containerDrag, + + renderGraph = function() { + graphics.beginRender(); + + // todo: move this check graphics + if (settings.renderLinks) { + graphics.renderLinks(); + } + graphics.renderNodes(); + graphics.endRender(); + }, + + onRenderFrame = function() { + isStable = layout.step() && !userInteraction; + renderGraph(); + + return !isStable; + }, + + renderIterations = function(iterationsCount) { + if (animationTimer) { + totalIterationsCount += iterationsCount; + return; + } + + if (iterationsCount) { + totalIterationsCount += iterationsCount; + + animationTimer = timer(function() { + return onRenderFrame(); + }, FRAME_INTERVAL); + } else { + currentStep = 0; + totalIterationsCount = 0; + animationTimer = timer(onRenderFrame, FRAME_INTERVAL); + } + }, + + resetStable = function() { + if (isPaused) { + return; + } + + isStable = false; + animationTimer.restart(); + }, + + prerender = function() { + // To get good initial positions for the graph + // perform several prerender steps in background. + var i; + if (typeof settings.prerender === 'number' && settings.prerender > 0) { + for (i = 0; i < settings.prerender; i += 1) { + layout.step(); + } + } + }, + + updateCenter = function() { + var graphRect = layout.getGraphRect(), + containerSize = getDimension(container); + + viewPortOffset.x = viewPortOffset.y = 0; + transform.offsetX = containerSize.width / 2 - (graphRect.x2 + graphRect.x1) / 2; + transform.offsetY = containerSize.height / 2 - (graphRect.y2 + graphRect.y1) / 2; + graphics.graphCenterChanged(transform.offsetX, transform.offsetY); + + updateCenterRequired = false; + }, + + createNodeUi = function(node) { + var nodePosition = layout.getNodePosition(node.id); + graphics.addNode(node, nodePosition); + }, + + removeNodeUi = function(node) { + graphics.releaseNode(node); + }, + + createLinkUi = function(link) { + var linkPosition = layout.getLinkPosition(link.id); + graphics.addLink(link, linkPosition); + }, + + removeLinkUi = function(link) { + graphics.releaseLink(link); + }, + + listenNodeEvents = function(node) { + if (!isInteractive('node')) { + return; + } + + var wasPinned = false; + + // TODO: This may not be memory efficient. Consider reusing handlers object. + inputManager.bindDragNDrop(node, { + onStart: function() { + wasPinned = layout.isNodePinned(node); + layout.pinNode(node, true); + userInteraction = true; + resetStable(); + }, + onDrag: function(e, offset) { + var oldPos = layout.getNodePosition(node.id); + layout.setNodePosition(node.id, + oldPos.x + offset.x / transform.scale, + oldPos.y + offset.y / transform.scale); + + userInteraction = true; + + renderGraph(); + }, + onStop: function() { + layout.pinNode(node, wasPinned); + userInteraction = false; + } + }); + }, - listenToEvents = function () { - windowEvents.on('resize', onWindowResized); + releaseNodeEvents = function(node) { + inputManager.bindDragNDrop(node, null); + }, - releaseContainerDragManager(); - if (isInteractive('drag')) { - containerDrag = dragndrop(container); - containerDrag.onDrag(function (e, offset) { - viewPortOffset.x += offset.x; - viewPortOffset.y += offset.y; - graphics.translateRel(offset.x, offset.y); + initDom = function() { + graphics.init(container); - renderGraph(); - }); - } + graph.forEachNode(createNodeUi); - if (isInteractive('scroll')) { - containerDrag.onScroll(function (e, scaleOffset, scrollPoint) { - scale(scaleOffset < 0, scrollPoint); - }); - } + if (settings.renderLinks) { + graph.forEachLink(createLinkUi); + } + }, - graph.forEachNode(listenNodeEvents); + releaseDom = function() { + graphics.release(container); + }, - releaseGraphEvents(); - graph.on('changed', onGraphChanged); - }, + processNodeChange = function(change) { + var node = change.node; - stopListenToEvents = function () { - rendererInitialized = false; - releaseGraphEvents(); - releaseContainerDragManager(); - windowEvents.off('resize', onWindowResized); - publicEvents.off(); - animationTimer.stop(); - - graph.forEachLink(function (link) { - if (settings.renderLinks) { removeLinkUi(link); } - }); - - graph.forEachNode(function (node) { - releaseNodeEvents(node); - removeNodeUi(node); - }); - - layout.dispose(); - releaseDom(); + if (change.changeType === 'add') { + createNodeUi(node); + listenNodeEvents(node); + if (updateCenterRequired) { + updateCenter(); + } + } else if (change.changeType === 'remove') { + releaseNodeEvents(node); + removeNodeUi(node); + if (graph.getNodesCount() === 0) { + updateCenterRequired = true; // Next time when node is added - center the graph. + } + } else if (change.changeType === 'update') { + releaseNodeEvents(node); + removeNodeUi(node); + + createNodeUi(node); + listenNodeEvents(node); + } + }, + + processLinkChange = function(change) { + var link = change.link; + if (change.changeType === 'add') { + if (settings.renderLinks) { + createLinkUi(link); + } + } else if (change.changeType === 'remove') { + if (settings.renderLinks) { + removeLinkUi(link); + } + } else if (change.changeType === 'update') { + throw 'Update type is not implemented. TODO: Implement me!'; + } + }, + + onGraphChanged = function(changes) { + var i, change; + for (i = 0; i < changes.length; i += 1) { + change = changes[i]; + if (change.node) { + processNodeChange(change); + } else if (change.link) { + processLinkChange(change); + } + } + + resetStable(); + }, + + onWindowResized = function() { + updateCenter(); + onRenderFrame(); + }, + + releaseContainerDragManager = function() { + if (containerDrag) { + containerDrag.release(); + containerDrag = null; + } + }, + + releaseGraphEvents = function() { + graph.off('changed', onGraphChanged); + }, + + scale = function(out, scrollPoint) { + if (!scrollPoint) { + var containerSize = getDimension(container); + scrollPoint = { + x: containerSize.width / 2, + y: containerSize.height / 2 }; + } + var scaleFactor = Math.pow(1 + 0.4, out ? -0.2 : 0.2); + transform.scale = graphics.scale(scaleFactor, scrollPoint); + + renderGraph(); + publicEvents.fire('scale', transform.scale); + + return transform.scale; + }, + + listenToEvents = function() { + windowEvents.on('resize', onWindowResized); + + releaseContainerDragManager(); + if (isInteractive('drag')) { + containerDrag = dragndrop(container); + containerDrag.onDrag(function(e, offset) { + viewPortOffset.x += offset.x; + viewPortOffset.y += offset.y; + graphics.translateRel(offset.x, offset.y); + + renderGraph(); + }); + } + + if (isInteractive('scroll')) { + containerDrag.onScroll(function(e, scaleOffset, scrollPoint) { + scale(scaleOffset < 0, scrollPoint); + }); + } + + graph.forEachNode(listenNodeEvents); + + releaseGraphEvents(); + graph.on('changed', onGraphChanged); + }, + + stopListenToEvents = function() { + rendererInitialized = false; + releaseGraphEvents(); + releaseContainerDragManager(); + windowEvents.off('resize', onWindowResized); + publicEvents.off(); + animationTimer.stop(); + + graph.forEachLink(function(link) { + if (settings.renderLinks) { + removeLinkUi(link); + } + }); - return { - /** - * Performs rendering of the graph. - * - * @param iterationsCount if specified renderer will run only given number of iterations - * and then stop. Otherwise graph rendering is performed infinitely. - * - * Note: if rendering stopped by used started dragging nodes or new nodes were added to the - * graph renderer will give run more iterations to reflect changes. - */ - run : function (iterationsCount) { - - if (!rendererInitialized) { - prepareSettings(); - prerender(); + graph.forEachNode(function(node) { + releaseNodeEvents(node); + removeNodeUi(node); + }); - updateCenter(); - initDom(); - listenToEvents(); + layout.dispose(); + releaseDom(); + }; - rendererInitialized = true; - } + return { + /** + * Performs rendering of the graph. + * + * @param iterationsCount if specified renderer will run only given number of iterations + * and then stop. Otherwise graph rendering is performed infinitely. + * + * Note: if rendering stopped by used started dragging nodes or new nodes were added to the + * graph renderer will give run more iterations to reflect changes. + */ + run: function(iterationsCount) { - renderIterations(iterationsCount); + if (!rendererInitialized) { + prepareSettings(); + prerender(); - return this; - }, + updateCenter(); + initDom(); + listenToEvents(); - reset : function () { - graphics.resetScale(); - updateCenter(); - transform.scale = 1; - }, + rendererInitialized = true; + } - pause : function () { - isPaused = true; - animationTimer.stop(); - }, + renderIterations(iterationsCount); - resume : function () { - isPaused = false; - animationTimer.restart(); - }, + return this; + }, - rerender : function () { - renderGraph(); - return this; - }, + reset: function() { + graphics.resetScale(); + updateCenter(); + transform.scale = 1; + }, - zoomOut: function () { - return scale(true); - }, + pause: function() { + isPaused = true; + animationTimer.stop(); + }, - zoomIn: function () { - return scale(false); - }, + resume: function() { + isPaused = false; + animationTimer.restart(); + }, - /** - * Centers renderer at x,y graph's coordinates - */ - moveTo: function (x, y) { - graphics.graphCenterChanged(transform.offsetX - x * transform.scale, transform.offsetY - y * transform.scale); - renderGraph(); - }, + rerender: function() { + renderGraph(); + return this; + }, - /** - * Gets current graphics object - */ - getGraphics: function () { - return graphics; - }, + zoomOut: function() { + return scale(true); + }, - /** - * Removes this renderer and deallocates all resources/timers - */ - dispose : function () { - stopListenToEvents(); // I quit! - }, + zoomIn: function() { + return scale(false); + }, - on : function (eventName, callback) { - publicEvents.addEventListener(eventName, callback); - return this; - }, + /** + * Centers renderer at x,y graph's coordinates + */ + moveTo: function(x, y) { + graphics.graphCenterChanged(transform.offsetX - x * transform.scale, transform.offsetY - y * transform.scale); + renderGraph(); + }, - off : function (eventName, callback) { - publicEvents.removeEventListener(eventName, callback); - return this; - } - }; + /** + * Gets current graphics object + */ + getGraphics: function() { + return graphics; + }, /** - * Checks whether given interaction (node/scroll) is enabled + * Removes this renderer and deallocates all resources/timers */ - function isInteractive(interactionName) { - if (typeof interactive === 'string') { - return interactive.indexOf(interactionName) >= 0; - } else if (typeof interactive === 'boolean') { - return interactive; - } - return true; // default setting + dispose: function() { + stopListenToEvents(); // I quit! + }, + + on: function(eventName, callback) { + publicEvents.addEventListener(eventName, callback); + return this; + }, + + off: function(eventName, callback) { + publicEvents.removeEventListener(eventName, callback); + return this; } + }; + + /** + * Checks whether given interaction (node/scroll) is enabled + */ + function isInteractive(interactionName) { + if (typeof interactive === 'string') { + return interactive.indexOf(interactionName) >= 0; + } else if (typeof interactive === 'boolean') { + return interactive; + } + return true; // default setting + } } - From 9c3c36e48fcd4202dba1218b45ee2fce9045e9b8 Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 25 Mar 2015 22:01:28 -0700 Subject: [PATCH 188/276] Replaced function variables with named functions --- src/View/renderer.js | 584 +++++++++++++++++++++---------------------- 1 file changed, 292 insertions(+), 292 deletions(-) diff --git a/src/View/renderer.js b/src/View/renderer.js index 1a62e05..842dcb0 100644 --- a/src/View/renderer.js +++ b/src/View/renderer.js @@ -82,300 +82,10 @@ function renderer(graph, settings) { offsetX: 0, offsetY: 0, scale: 1 - }; - - var prepareSettings = function() { - container = container || window.document.body; - layout = layout || forceDirected(graph, forceDirected.simulator({ - springLength: 80, - springCoeff: 0.0002, - })); - graphics = graphics || svgGraphics(graph, { - container: container - }); - - if (!settings.hasOwnProperty('renderLinks')) { - settings.renderLinks = true; - } - - settings.prerender = settings.prerender || 0; - inputManager = (graphics.inputManager || domInputManager)(graph, graphics); - }, - publicEvents = eventify({}), - containerDrag, - - renderGraph = function() { - graphics.beginRender(); - - // todo: move this check graphics - if (settings.renderLinks) { - graphics.renderLinks(); - } - graphics.renderNodes(); - graphics.endRender(); - }, - - onRenderFrame = function() { - isStable = layout.step() && !userInteraction; - renderGraph(); - - return !isStable; - }, - - renderIterations = function(iterationsCount) { - if (animationTimer) { - totalIterationsCount += iterationsCount; - return; - } - - if (iterationsCount) { - totalIterationsCount += iterationsCount; - - animationTimer = timer(function() { - return onRenderFrame(); - }, FRAME_INTERVAL); - } else { - currentStep = 0; - totalIterationsCount = 0; - animationTimer = timer(onRenderFrame, FRAME_INTERVAL); - } - }, - - resetStable = function() { - if (isPaused) { - return; - } - - isStable = false; - animationTimer.restart(); - }, - - prerender = function() { - // To get good initial positions for the graph - // perform several prerender steps in background. - var i; - if (typeof settings.prerender === 'number' && settings.prerender > 0) { - for (i = 0; i < settings.prerender; i += 1) { - layout.step(); - } - } - }, - - updateCenter = function() { - var graphRect = layout.getGraphRect(), - containerSize = getDimension(container); - - viewPortOffset.x = viewPortOffset.y = 0; - transform.offsetX = containerSize.width / 2 - (graphRect.x2 + graphRect.x1) / 2; - transform.offsetY = containerSize.height / 2 - (graphRect.y2 + graphRect.y1) / 2; - graphics.graphCenterChanged(transform.offsetX, transform.offsetY); - - updateCenterRequired = false; - }, - - createNodeUi = function(node) { - var nodePosition = layout.getNodePosition(node.id); - graphics.addNode(node, nodePosition); - }, - - removeNodeUi = function(node) { - graphics.releaseNode(node); - }, - - createLinkUi = function(link) { - var linkPosition = layout.getLinkPosition(link.id); - graphics.addLink(link, linkPosition); - }, - - removeLinkUi = function(link) { - graphics.releaseLink(link); - }, - - listenNodeEvents = function(node) { - if (!isInteractive('node')) { - return; - } - - var wasPinned = false; - - // TODO: This may not be memory efficient. Consider reusing handlers object. - inputManager.bindDragNDrop(node, { - onStart: function() { - wasPinned = layout.isNodePinned(node); - layout.pinNode(node, true); - userInteraction = true; - resetStable(); - }, - onDrag: function(e, offset) { - var oldPos = layout.getNodePosition(node.id); - layout.setNodePosition(node.id, - oldPos.x + offset.x / transform.scale, - oldPos.y + offset.y / transform.scale); - - userInteraction = true; - - renderGraph(); - }, - onStop: function() { - layout.pinNode(node, wasPinned); - userInteraction = false; - } - }); - }, - - releaseNodeEvents = function(node) { - inputManager.bindDragNDrop(node, null); - }, - - initDom = function() { - graphics.init(container); - - graph.forEachNode(createNodeUi); - - if (settings.renderLinks) { - graph.forEachLink(createLinkUi); - } }, - releaseDom = function() { - graphics.release(container); - }, - - processNodeChange = function(change) { - var node = change.node; - - if (change.changeType === 'add') { - createNodeUi(node); - listenNodeEvents(node); - if (updateCenterRequired) { - updateCenter(); - } - } else if (change.changeType === 'remove') { - releaseNodeEvents(node); - removeNodeUi(node); - if (graph.getNodesCount() === 0) { - updateCenterRequired = true; // Next time when node is added - center the graph. - } - } else if (change.changeType === 'update') { - releaseNodeEvents(node); - removeNodeUi(node); - - createNodeUi(node); - listenNodeEvents(node); - } - }, - - processLinkChange = function(change) { - var link = change.link; - if (change.changeType === 'add') { - if (settings.renderLinks) { - createLinkUi(link); - } - } else if (change.changeType === 'remove') { - if (settings.renderLinks) { - removeLinkUi(link); - } - } else if (change.changeType === 'update') { - throw 'Update type is not implemented. TODO: Implement me!'; - } - }, - - onGraphChanged = function(changes) { - var i, change; - for (i = 0; i < changes.length; i += 1) { - change = changes[i]; - if (change.node) { - processNodeChange(change); - } else if (change.link) { - processLinkChange(change); - } - } - - resetStable(); - }, - - onWindowResized = function() { - updateCenter(); - onRenderFrame(); - }, - - releaseContainerDragManager = function() { - if (containerDrag) { - containerDrag.release(); - containerDrag = null; - } - }, - - releaseGraphEvents = function() { - graph.off('changed', onGraphChanged); - }, - - scale = function(out, scrollPoint) { - if (!scrollPoint) { - var containerSize = getDimension(container); - scrollPoint = { - x: containerSize.width / 2, - y: containerSize.height / 2 - }; - } - var scaleFactor = Math.pow(1 + 0.4, out ? -0.2 : 0.2); - transform.scale = graphics.scale(scaleFactor, scrollPoint); - - renderGraph(); - publicEvents.fire('scale', transform.scale); - - return transform.scale; - }, - - listenToEvents = function() { - windowEvents.on('resize', onWindowResized); - - releaseContainerDragManager(); - if (isInteractive('drag')) { - containerDrag = dragndrop(container); - containerDrag.onDrag(function(e, offset) { - viewPortOffset.x += offset.x; - viewPortOffset.y += offset.y; - graphics.translateRel(offset.x, offset.y); - - renderGraph(); - }); - } - - if (isInteractive('scroll')) { - containerDrag.onScroll(function(e, scaleOffset, scrollPoint) { - scale(scaleOffset < 0, scrollPoint); - }); - } - - graph.forEachNode(listenNodeEvents); - - releaseGraphEvents(); - graph.on('changed', onGraphChanged); - }, - - stopListenToEvents = function() { - rendererInitialized = false; - releaseGraphEvents(); - releaseContainerDragManager(); - windowEvents.off('resize', onWindowResized); - publicEvents.off(); - animationTimer.stop(); - - graph.forEachLink(function(link) { - if (settings.renderLinks) { - removeLinkUi(link); - } - }); - - graph.forEachNode(function(node) { - releaseNodeEvents(node); - removeNodeUi(node); - }); - - layout.dispose(); - releaseDom(); - }; + publicEvents = eventify({}), + containerDrag; return { /** @@ -478,4 +188,294 @@ function renderer(graph, settings) { } return true; // default setting } + + function prepareSettings() { + container = container || window.document.body; + layout = layout || forceDirected(graph, forceDirected.simulator({ + springLength: 80, + springCoeff: 0.0002, + })); + graphics = graphics || svgGraphics(graph, { + container: container + }); + + if (!settings.hasOwnProperty('renderLinks')) { + settings.renderLinks = true; + } + + settings.prerender = settings.prerender || 0; + inputManager = (graphics.inputManager || domInputManager)(graph, graphics); + } + + function renderGraph() { + graphics.beginRender(); + + // todo: move this check graphics + if (settings.renderLinks) { + graphics.renderLinks(); + } + graphics.renderNodes(); + graphics.endRender(); + } + + function onRenderFrame() { + isStable = layout.step() && !userInteraction; + renderGraph(); + + return !isStable; + } + + function renderIterations(iterationsCount) { + if (animationTimer) { + totalIterationsCount += iterationsCount; + return; + } + + if (iterationsCount) { + totalIterationsCount += iterationsCount; + + animationTimer = timer(function() { + return onRenderFrame(); + }, FRAME_INTERVAL); + } else { + currentStep = 0; + totalIterationsCount = 0; + animationTimer = timer(onRenderFrame, FRAME_INTERVAL); + } + } + + function resetStable() { + if (isPaused) { + return; + } + + isStable = false; + animationTimer.restart(); + } + + function prerender() { + // To get good initial positions for the graph + // perform several prerender steps in background. + if (typeof settings.prerender === 'number' && settings.prerender > 0) { + for (var i = 0; i < settings.prerender; i += 1) { + layout.step(); + } + } + } + + function updateCenter() { + var graphRect = layout.getGraphRect(), + containerSize = getDimension(container); + + viewPortOffset.x = viewPortOffset.y = 0; + transform.offsetX = containerSize.width / 2 - (graphRect.x2 + graphRect.x1) / 2; + transform.offsetY = containerSize.height / 2 - (graphRect.y2 + graphRect.y1) / 2; + graphics.graphCenterChanged(transform.offsetX, transform.offsetY); + + updateCenterRequired = false; + } + + function createNodeUi(node) { + var nodePosition = layout.getNodePosition(node.id); + graphics.addNode(node, nodePosition); + } + + function removeNodeUi(node) { + graphics.releaseNode(node); + } + + function createLinkUi(link) { + var linkPosition = layout.getLinkPosition(link.id); + graphics.addLink(link, linkPosition); + } + + function removeLinkUi(link) { + graphics.releaseLink(link); + } + + function listenNodeEvents(node) { + if (!isInteractive('node')) { + return; + } + + var wasPinned = false; + + // TODO: This may not be memory efficient. Consider reusing handlers object. + inputManager.bindDragNDrop(node, { + onStart: function() { + wasPinned = layout.isNodePinned(node); + layout.pinNode(node, true); + userInteraction = true; + resetStable(); + }, + onDrag: function(e, offset) { + var oldPos = layout.getNodePosition(node.id); + layout.setNodePosition(node.id, + oldPos.x + offset.x / transform.scale, + oldPos.y + offset.y / transform.scale); + + userInteraction = true; + + renderGraph(); + }, + onStop: function() { + layout.pinNode(node, wasPinned); + userInteraction = false; + } + }); + } + + function releaseNodeEvents(node) { + inputManager.bindDragNDrop(node, null); + } + + function initDom() { + graphics.init(container); + + graph.forEachNode(createNodeUi); + + if (settings.renderLinks) { + graph.forEachLink(createLinkUi); + } + } + + function releaseDom() { + graphics.release(container); + } + + function processNodeChange(change) { + var node = change.node; + + if (change.changeType === 'add') { + createNodeUi(node); + listenNodeEvents(node); + if (updateCenterRequired) { + updateCenter(); + } + } else if (change.changeType === 'remove') { + releaseNodeEvents(node); + removeNodeUi(node); + if (graph.getNodesCount() === 0) { + updateCenterRequired = true; // Next time when node is added - center the graph. + } + } else if (change.changeType === 'update') { + releaseNodeEvents(node); + removeNodeUi(node); + + createNodeUi(node); + listenNodeEvents(node); + } + } + + function processLinkChange(change) { + var link = change.link; + if (change.changeType === 'add') { + if (settings.renderLinks) { + createLinkUi(link); + } + } else if (change.changeType === 'remove') { + if (settings.renderLinks) { + removeLinkUi(link); + } + } else if (change.changeType === 'update') { + throw 'Update type is not implemented. TODO: Implement me!'; + } + } + + function onGraphChanged(changes) { + var i, change; + for (i = 0; i < changes.length; i += 1) { + change = changes[i]; + if (change.node) { + processNodeChange(change); + } else if (change.link) { + processLinkChange(change); + } + } + + resetStable(); + } + + function onWindowResized() { + updateCenter(); + onRenderFrame(); + } + + function releaseContainerDragManager() { + if (containerDrag) { + containerDrag.release(); + containerDrag = null; + } + } + + function releaseGraphEvents() { + graph.off('changed', onGraphChanged); + } + + function scale(out, scrollPoint) { + if (!scrollPoint) { + var containerSize = getDimension(container); + scrollPoint = { + x: containerSize.width / 2, + y: containerSize.height / 2 + }; + } + var scaleFactor = Math.pow(1 + 0.4, out ? -0.2 : 0.2); + transform.scale = graphics.scale(scaleFactor, scrollPoint); + + renderGraph(); + publicEvents.fire('scale', transform.scale); + + return transform.scale; + } + + function listenToEvents() { + windowEvents.on('resize', onWindowResized); + + releaseContainerDragManager(); + if (isInteractive('drag')) { + containerDrag = dragndrop(container); + containerDrag.onDrag(function(e, offset) { + viewPortOffset.x += offset.x; + viewPortOffset.y += offset.y; + graphics.translateRel(offset.x, offset.y); + + renderGraph(); + }); + } + + if (isInteractive('scroll')) { + containerDrag.onScroll(function(e, scaleOffset, scrollPoint) { + scale(scaleOffset < 0, scrollPoint); + }); + } + + graph.forEachNode(listenNodeEvents); + + releaseGraphEvents(); + graph.on('changed', onGraphChanged); + } + + function stopListenToEvents() { + rendererInitialized = false; + releaseGraphEvents(); + releaseContainerDragManager(); + windowEvents.off('resize', onWindowResized); + publicEvents.off(); + animationTimer.stop(); + + graph.forEachLink(function(link) { + if (settings.renderLinks) { + removeLinkUi(link); + } + }); + + graph.forEachNode(function(node) { + releaseNodeEvents(node); + removeNodeUi(node); + }); + + layout.dispose(); + releaseDom(); + } } From 1fb5e5fe0fecc27a5cfdd34d43f748e68d73decb Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 8 Apr 2015 20:30:22 -0700 Subject: [PATCH 189/276] Updated to latest ngraph.graph --- dist/vivagraph.js | 724 +++++++++++++++++++++--------------------- dist/vivagraph.min.js | 4 +- package.json | 12 +- src/version.js | 2 +- 4 files changed, 375 insertions(+), 367 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index e9a6e51..0299416 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -2254,7 +2254,8 @@ function createGraph(options) { * its data is extended with whatever comes in 'data' argument. * * @param nodeId the node's identifier. A string or number is preferred. - * note: Node id should not contain ''. This will break link identifiers + * note: If you request options.uniqueLinkId, then node id should not + * contain '👉 '. This will break link identifiers * @param [data] additional data for the node being added. If node already * exists its data object is augmented with the new one. * @@ -2415,8 +2416,8 @@ function createGraph(options) { function on() { // now it's time to start tracking stuff: - enterModification = enterModificationReal; - exitModification = exitModificationReal; + graphPart.beginUpdate = enterModification = enterModificationReal; + graphPart.endUpdate = exitModification = exitModificationReal; recordLinkChange = recordLinkChangeReal; recordNodeChange = recordNodeChangeReal; @@ -4243,426 +4244,433 @@ var dragndrop = require('../Input/dragndrop.js'); * } */ function renderer(graph, settings) { - // TODO: This class is getting hard to understand. Consider refactoring. - // TODO: I have a technical debt here: fix scaling/recentering! Currently it's a total mess. - var FRAME_INTERVAL = 30; - - settings = settings || {}; - - var layout = settings.layout, - graphics = settings.graphics, - container = settings.container, - interactive = settings.interactive !== undefined ? settings.interactive : true, - inputManager, - animationTimer, - rendererInitialized = false, - updateCenterRequired = true, - - currentStep = 0, - totalIterationsCount = 0, - isStable = false, - userInteraction = false, - isPaused = false, - - viewPortOffset = { - x : 0, - y : 0 - }, + // TODO: This class is getting hard to understand. Consider refactoring. + // TODO: I have a technical debt here: fix scaling/recentering! Currently it's a total mess. + var FRAME_INTERVAL = 30; + + settings = settings || {}; + + var layout = settings.layout, + graphics = settings.graphics, + container = settings.container, + interactive = settings.interactive !== undefined ? settings.interactive : true, + inputManager, + animationTimer, + rendererInitialized = false, + updateCenterRequired = true, + + currentStep = 0, + totalIterationsCount = 0, + isStable = false, + userInteraction = false, + isPaused = false, + + viewPortOffset = { + x: 0, + y: 0 + }, - transform = { - offsetX : 0, - offsetY : 0, - scale : 1 - }; + transform = { + offsetX: 0, + offsetY: 0, + scale: 1 + }, - var prepareSettings = function () { - container = container || window.document.body; - layout = layout || forceDirected(graph, forceDirected.simulator({ - springLength: 80, - springCoeff: 0.0002, - })); - graphics = graphics || svgGraphics(graph, {container : container}); + publicEvents = eventify({}), + containerDrag; - if (!settings.hasOwnProperty('renderLinks')) { - settings.renderLinks = true; - } + return { + /** + * Performs rendering of the graph. + * + * @param iterationsCount if specified renderer will run only given number of iterations + * and then stop. Otherwise graph rendering is performed infinitely. + * + * Note: if rendering stopped by used started dragging nodes or new nodes were added to the + * graph renderer will give run more iterations to reflect changes. + */ + run: function(iterationsCount) { - settings.prerender = settings.prerender || 0; - inputManager = (graphics.inputManager || domInputManager)(graph, graphics); - }, - publicEvents = eventify({}), - containerDrag, + if (!rendererInitialized) { + prepareSettings(); + prerender(); - renderGraph = function () { - graphics.beginRender(); + updateCenter(); + initDom(); + listenToEvents(); - // todo: move this check graphics - if (settings.renderLinks) { - graphics.renderLinks(); - } - graphics.renderNodes(); - graphics.endRender(); - }, + rendererInitialized = true; + } - onRenderFrame = function () { - isStable = layout.step() && !userInteraction; - renderGraph(); + renderIterations(iterationsCount); - return !isStable; - }, + return this; + }, - renderIterations = function (iterationsCount) { - if (animationTimer) { - totalIterationsCount += iterationsCount; - return; - } + reset: function() { + graphics.resetScale(); + updateCenter(); + transform.scale = 1; + }, - if (iterationsCount) { - totalIterationsCount += iterationsCount; + pause: function() { + isPaused = true; + animationTimer.stop(); + }, - animationTimer = timer(function () { - return onRenderFrame(); - }, FRAME_INTERVAL); - } else { - currentStep = 0; - totalIterationsCount = 0; - animationTimer = timer(onRenderFrame, FRAME_INTERVAL); - } - }, + resume: function() { + isPaused = false; + animationTimer.restart(); + }, - resetStable = function () { - if(isPaused) { - return; - } + rerender: function() { + renderGraph(); + return this; + }, - isStable = false; - animationTimer.restart(); - }, + zoomOut: function() { + return scale(true); + }, - prerender = function () { - // To get good initial positions for the graph - // perform several prerender steps in background. - var i; - if (typeof settings.prerender === 'number' && settings.prerender > 0) { - for (i = 0; i < settings.prerender; i += 1) { - layout.step(); - } - } - }, + zoomIn: function() { + return scale(false); + }, - updateCenter = function () { - var graphRect = layout.getGraphRect(), - containerSize = getDimension(container); + /** + * Centers renderer at x,y graph's coordinates + */ + moveTo: function(x, y) { + graphics.graphCenterChanged(transform.offsetX - x * transform.scale, transform.offsetY - y * transform.scale); + renderGraph(); + }, - viewPortOffset.x = viewPortOffset.y = 0; - transform.offsetX = containerSize.width / 2 - (graphRect.x2 + graphRect.x1) / 2; - transform.offsetY = containerSize.height / 2 - (graphRect.y2 + graphRect.y1) / 2; - graphics.graphCenterChanged(transform.offsetX, transform.offsetY); + /** + * Gets current graphics object + */ + getGraphics: function() { + return graphics; + }, - updateCenterRequired = false; - }, + /** + * Removes this renderer and deallocates all resources/timers + */ + dispose: function() { + stopListenToEvents(); // I quit! + }, - createNodeUi = function (node) { - var nodePosition = layout.getNodePosition(node.id); - graphics.addNode(node, nodePosition); - }, + on: function(eventName, callback) { + publicEvents.addEventListener(eventName, callback); + return this; + }, - removeNodeUi = function (node) { - graphics.releaseNode(node); - }, + off: function(eventName, callback) { + publicEvents.removeEventListener(eventName, callback); + return this; + } + }; - createLinkUi = function (link) { - var linkPosition = layout.getLinkPosition(link.id); - graphics.addLink(link, linkPosition); - }, + /** + * Checks whether given interaction (node/scroll) is enabled + */ + function isInteractive(interactionName) { + if (typeof interactive === 'string') { + return interactive.indexOf(interactionName) >= 0; + } else if (typeof interactive === 'boolean') { + return interactive; + } + return true; // default setting + } - removeLinkUi = function (link) { - graphics.releaseLink(link); - }, + function prepareSettings() { + container = container || window.document.body; + layout = layout || forceDirected(graph, forceDirected.simulator({ + springLength: 80, + springCoeff: 0.0002, + })); + graphics = graphics || svgGraphics(graph, { + container: container + }); - listenNodeEvents = function (node) { - if (!isInteractive('node')) { - return; - } + if (!settings.hasOwnProperty('renderLinks')) { + settings.renderLinks = true; + } - var wasPinned = false; - - // TODO: This may not be memory efficient. Consider reusing handlers object. - inputManager.bindDragNDrop(node, { - onStart : function () { - wasPinned = layout.isNodePinned(node); - layout.pinNode(node, true); - userInteraction = true; - resetStable(); - }, - onDrag : function (e, offset) { - var oldPos = layout.getNodePosition(node.id); - layout.setNodePosition(node.id, - oldPos.x + offset.x / transform.scale, - oldPos.y + offset.y / transform.scale); - - userInteraction = true; - - renderGraph(); - }, - onStop : function () { - layout.pinNode(node, wasPinned); - userInteraction = false; - } - }); - }, + settings.prerender = settings.prerender || 0; + inputManager = (graphics.inputManager || domInputManager)(graph, graphics); + } - releaseNodeEvents = function (node) { - inputManager.bindDragNDrop(node, null); - }, + function renderGraph() { + graphics.beginRender(); - initDom = function () { - graphics.init(container); + // todo: move this check graphics + if (settings.renderLinks) { + graphics.renderLinks(); + } + graphics.renderNodes(); + graphics.endRender(); + } - graph.forEachNode(createNodeUi); + function onRenderFrame() { + isStable = layout.step() && !userInteraction; + renderGraph(); - if (settings.renderLinks) { - graph.forEachLink(createLinkUi); - } - }, + return !isStable; + } - releaseDom = function () { - graphics.release(container); - }, + function renderIterations(iterationsCount) { + if (animationTimer) { + totalIterationsCount += iterationsCount; + return; + } - processNodeChange = function (change) { - var node = change.node; + if (iterationsCount) { + totalIterationsCount += iterationsCount; - if (change.changeType === 'add') { - createNodeUi(node); - listenNodeEvents(node); - if (updateCenterRequired) { - updateCenter(); - } - } else if (change.changeType === 'remove') { - releaseNodeEvents(node); - removeNodeUi(node); - if (graph.getNodesCount() === 0) { - updateCenterRequired = true; // Next time when node is added - center the graph. - } - } else if (change.changeType === 'update') { - releaseNodeEvents(node); - removeNodeUi(node); + animationTimer = timer(function() { + return onRenderFrame(); + }, FRAME_INTERVAL); + } else { + currentStep = 0; + totalIterationsCount = 0; + animationTimer = timer(onRenderFrame, FRAME_INTERVAL); + } + } - createNodeUi(node); - listenNodeEvents(node); - } - }, + function resetStable() { + if (isPaused) { + return; + } - processLinkChange = function (change) { - var link = change.link; - if (change.changeType === 'add') { - if (settings.renderLinks) { createLinkUi(link); } - } else if (change.changeType === 'remove') { - if (settings.renderLinks) { removeLinkUi(link); } - } else if (change.changeType === 'update') { - throw 'Update type is not implemented. TODO: Implement me!'; - } - }, + isStable = false; + animationTimer.restart(); + } - onGraphChanged = function (changes) { - var i, change; - for (i = 0; i < changes.length; i += 1) { - change = changes[i]; - if (change.node) { - processNodeChange(change); - } else if (change.link) { - processLinkChange(change); - } - } + function prerender() { + // To get good initial positions for the graph + // perform several prerender steps in background. + if (typeof settings.prerender === 'number' && settings.prerender > 0) { + for (var i = 0; i < settings.prerender; i += 1) { + layout.step(); + } + } + } - resetStable(); - }, + function updateCenter() { + var graphRect = layout.getGraphRect(), + containerSize = getDimension(container); - onWindowResized = function () { - updateCenter(); - onRenderFrame(); - }, + viewPortOffset.x = viewPortOffset.y = 0; + transform.offsetX = containerSize.width / 2 - (graphRect.x2 + graphRect.x1) / 2; + transform.offsetY = containerSize.height / 2 - (graphRect.y2 + graphRect.y1) / 2; + graphics.graphCenterChanged(transform.offsetX, transform.offsetY); - releaseContainerDragManager = function () { - if (containerDrag) { - containerDrag.release(); - containerDrag = null; - } - }, + updateCenterRequired = false; + } - releaseGraphEvents = function () { - graph.off('changed', onGraphChanged); - }, + function createNodeUi(node) { + var nodePosition = layout.getNodePosition(node.id); + graphics.addNode(node, nodePosition); + } - scale = function (out, scrollPoint) { - if (!scrollPoint) { - var containerSize = getDimension(container); - scrollPoint = { - x: containerSize.width/2, - y: containerSize.height/2 - }; - } - var scaleFactor = Math.pow(1 + 0.4, out ? -0.2 : 0.2); - transform.scale = graphics.scale(scaleFactor, scrollPoint); + function removeNodeUi(node) { + graphics.releaseNode(node); + } - renderGraph(); - publicEvents.fire('scale', transform.scale); + function createLinkUi(link) { + var linkPosition = layout.getLinkPosition(link.id); + graphics.addLink(link, linkPosition); + } - return transform.scale; - }, + function removeLinkUi(link) { + graphics.releaseLink(link); + } - listenToEvents = function () { - windowEvents.on('resize', onWindowResized); + function listenNodeEvents(node) { + if (!isInteractive('node')) { + return; + } - releaseContainerDragManager(); - if (isInteractive('drag')) { - containerDrag = dragndrop(container); - containerDrag.onDrag(function (e, offset) { - viewPortOffset.x += offset.x; - viewPortOffset.y += offset.y; - graphics.translateRel(offset.x, offset.y); + var wasPinned = false; + + // TODO: This may not be memory efficient. Consider reusing handlers object. + inputManager.bindDragNDrop(node, { + onStart: function() { + wasPinned = layout.isNodePinned(node); + layout.pinNode(node, true); + userInteraction = true; + resetStable(); + }, + onDrag: function(e, offset) { + var oldPos = layout.getNodePosition(node.id); + layout.setNodePosition(node.id, + oldPos.x + offset.x / transform.scale, + oldPos.y + offset.y / transform.scale); + + userInteraction = true; + + renderGraph(); + }, + onStop: function() { + layout.pinNode(node, wasPinned); + userInteraction = false; + } + }); + } - renderGraph(); - }); - } + function releaseNodeEvents(node) { + inputManager.bindDragNDrop(node, null); + } - if (isInteractive('scroll')) { - containerDrag.onScroll(function (e, scaleOffset, scrollPoint) { - scale(scaleOffset < 0, scrollPoint); - }); - } + function initDom() { + graphics.init(container); - graph.forEachNode(listenNodeEvents); + graph.forEachNode(createNodeUi); - releaseGraphEvents(); - graph.on('changed', onGraphChanged); - }, + if (settings.renderLinks) { + graph.forEachLink(createLinkUi); + } + } - stopListenToEvents = function () { - rendererInitialized = false; - releaseGraphEvents(); - releaseContainerDragManager(); - windowEvents.off('resize', onWindowResized); - publicEvents.off(); - animationTimer.stop(); - - graph.forEachLink(function (link) { - if (settings.renderLinks) { removeLinkUi(link); } - }); - - graph.forEachNode(function (node) { - releaseNodeEvents(node); - removeNodeUi(node); - }); - - layout.dispose(); - releaseDom(); - }; + function releaseDom() { + graphics.release(container); + } - return { - /** - * Performs rendering of the graph. - * - * @param iterationsCount if specified renderer will run only given number of iterations - * and then stop. Otherwise graph rendering is performed infinitely. - * - * Note: if rendering stopped by used started dragging nodes or new nodes were added to the - * graph renderer will give run more iterations to reflect changes. - */ - run : function (iterationsCount) { + function processNodeChange(change) { + var node = change.node; - if (!rendererInitialized) { - prepareSettings(); - prerender(); + if (change.changeType === 'add') { + createNodeUi(node); + listenNodeEvents(node); + if (updateCenterRequired) { + updateCenter(); + } + } else if (change.changeType === 'remove') { + releaseNodeEvents(node); + removeNodeUi(node); + if (graph.getNodesCount() === 0) { + updateCenterRequired = true; // Next time when node is added - center the graph. + } + } else if (change.changeType === 'update') { + releaseNodeEvents(node); + removeNodeUi(node); - updateCenter(); - initDom(); - listenToEvents(); + createNodeUi(node); + listenNodeEvents(node); + } + } - rendererInitialized = true; - } + function processLinkChange(change) { + var link = change.link; + if (change.changeType === 'add') { + if (settings.renderLinks) { + createLinkUi(link); + } + } else if (change.changeType === 'remove') { + if (settings.renderLinks) { + removeLinkUi(link); + } + } else if (change.changeType === 'update') { + throw 'Update type is not implemented. TODO: Implement me!'; + } + } - renderIterations(iterationsCount); + function onGraphChanged(changes) { + var i, change; + for (i = 0; i < changes.length; i += 1) { + change = changes[i]; + if (change.node) { + processNodeChange(change); + } else if (change.link) { + processLinkChange(change); + } + } - return this; - }, + resetStable(); + } - reset : function () { - graphics.resetScale(); - updateCenter(); - transform.scale = 1; - }, + function onWindowResized() { + updateCenter(); + onRenderFrame(); + } - pause : function () { - isPaused = true; - animationTimer.stop(); - }, + function releaseContainerDragManager() { + if (containerDrag) { + containerDrag.release(); + containerDrag = null; + } + } - resume : function () { - isPaused = false; - animationTimer.restart(); - }, + function releaseGraphEvents() { + graph.off('changed', onGraphChanged); + } - rerender : function () { - renderGraph(); - return this; - }, + function scale(out, scrollPoint) { + if (!scrollPoint) { + var containerSize = getDimension(container); + scrollPoint = { + x: containerSize.width / 2, + y: containerSize.height / 2 + }; + } + var scaleFactor = Math.pow(1 + 0.4, out ? -0.2 : 0.2); + transform.scale = graphics.scale(scaleFactor, scrollPoint); - zoomOut: function () { - return scale(true); - }, + renderGraph(); + publicEvents.fire('scale', transform.scale); - zoomIn: function () { - return scale(false); - }, + return transform.scale; + } - /** - * Centers renderer at x,y graph's coordinates - */ - moveTo: function (x, y) { - graphics.graphCenterChanged(transform.offsetX - x * transform.scale, transform.offsetY - y * transform.scale); - renderGraph(); - }, + function listenToEvents() { + windowEvents.on('resize', onWindowResized); - /** - * Gets current graphics object - */ - getGraphics: function () { - return graphics; - }, + releaseContainerDragManager(); + if (isInteractive('drag')) { + containerDrag = dragndrop(container); + containerDrag.onDrag(function(e, offset) { + viewPortOffset.x += offset.x; + viewPortOffset.y += offset.y; + graphics.translateRel(offset.x, offset.y); - /** - * Removes this renderer and deallocates all resources/timers - */ - dispose : function () { - stopListenToEvents(); // I quit! - }, + renderGraph(); + }); + } - on : function (eventName, callback) { - publicEvents.addEventListener(eventName, callback); - return this; - }, + if (isInteractive('scroll')) { + containerDrag.onScroll(function(e, scaleOffset, scrollPoint) { + scale(scaleOffset < 0, scrollPoint); + }); + } - off : function (eventName, callback) { - publicEvents.removeEventListener(eventName, callback); - return this; - } - }; + graph.forEachNode(listenNodeEvents); - /** - * Checks whether given interaction (node/scroll) is enabled - */ - function isInteractive(interactionName) { - if (typeof interactive === 'string') { - return interactive.indexOf(interactionName) >= 0; - } else if (typeof interactive === 'boolean') { - return interactive; - } - return true; // default setting - } -} + releaseGraphEvents(); + graph.on('changed', onGraphChanged); + } + + function stopListenToEvents() { + rendererInitialized = false; + releaseGraphEvents(); + releaseContainerDragManager(); + windowEvents.off('resize', onWindowResized); + publicEvents.off(); + animationTimer.stop(); + + graph.forEachLink(function(link) { + if (settings.renderLinks) { + removeLinkUi(link); + } + }); + + graph.forEachNode(function(node) { + releaseNodeEvents(node); + removeNodeUi(node); + }); + layout.dispose(); + releaseDom(); + } +} },{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.forcelayout":7,"ngraph.graph":24}],50:[function(require,module,exports){ /** @@ -6844,7 +6852,7 @@ function webglSquare(size, color) { },{"./parseColor.js":52}],63:[function(require,module,exports){ // todo: this should be generated at build time. -module.exports = '0.7.7'; +module.exports = '0.7.8'; },{}]},{},[1])(1) }); \ No newline at end of file diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 13ba7ba..990cd36 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-s*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=t},{}],3:[function(e,n){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n){function t(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function g(e){var n=w[e];n.mass=y(e)}function h(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function m(e){var n=w[e];return n||(c(e),n=w[e]),n}function y(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var x=e("ngraph.physics.simulator");t=t||x(),o(t,"physicsSimulator").has("step","getBestNewBodyPosition","addBodyAt");var w="function"==typeof Object.create?Object.create(null):{},b={},E=t.settings.springTransform||r;f(),u();var L={step:function(){return t.step()},getNodePosition:function(e){return m(e).pos},setNodePosition:function(e){var n=m(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return t.getBBox()},pinNode:function(e,n){var t=m(e.id);t.isPinned=!!n},isNodePinned:function(e){return m(e.id).isPinned},dispose:function(){n.off("changed",s)},getBody:a,getSpring:i,simulator:t};return L}function r(){}n.exports=t,n.exports.simulator=e("ngraph.physics.simulator");var o=e("varta")},{"ngraph.physics.simulator":8,varta:21}],8:[function(e,n){function t(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.force.reset(),v.updateBodyForce(e),m.update(e);for(n=p.length;n--;)h.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),u=n.createBounds||e("./lib/bounds"),s=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),g=u(l,n),h=f(n),m=s(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return g.update(),en))return l.splice(n,1),0===l.length&&g.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return g.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=t},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":25,"ngraph.quadtreebh":17}],9:[function(e,n){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;ut;++t){var s=e[t],f=n/s.mass;s.velocity.x+=f*s.force.x,s.velocity.y+=f*s.force.y;var c=s.velocity.x,d=s.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=t},{}],13:[function(e,n){function t(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=t},{}],14:[function(e,n){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":25,"ngraph.random":26}],15:[function(e,n){function t(e,n,t){var o="[object Array]"===Object.prototype.toString.call(t);if(o)for(var i=0;i0&&u(s.pos,a.pos));if(0===f&&u(s.pos,a.pos))return}c.push(i,s),c.push(i,a)}else{var h=a.pos.x,m=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*h,i.massY=i.massY+a.mass*m;var y=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;if(h>w){y+=1;var L=x;x=w,w+=w-L}if(m>E){y+=2;var P=b;b=E,E+=E-P}var N=t(i,y);N?c.push(N,a):(N=v(),N.left=x,N.top=b,N.right=w,N.bottom=E,N.body=a,r(i,y,N))}}},m=function(e){var n,t,r,i,a=f,u=0,c=0,l=1,p=0,v=1;for(a[0]=g;l;){var h=a[p],m=h.body;l-=1,p+=1;var y=m!==e;m&&y?(t=m.pos.x-e.pos.x,r=m.pos.y-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),n=s*m.mass*e.mass/(i*i*i),u+=n*t,c+=n*r):y&&(t=h.massX/h.mass-e.pos.x,r=h.massY/h.mass-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),(h.right-h.left)/iu&&(t=u),u>o&&(o=u),r>s&&(r=s),s>i&&(i=s)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,p=0,g=v(),g.left=t,g.right=o,g.top=r,g.bottom=i,n=a-1,n>0&&(g.body=e[n]);n--;)h(e[n],g)};return{insertBodies:y,updateBodyForce:m,options:function(e){return e?("number"==typeof e.gravity&&(s=e.gravity),"number"==typeof e.theta&&(d=e.theta),this):{gravity:s,theta:d}}}}},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":26}],18:[function(e,n){function t(){this.stack=[],this.popIdx=0}function r(e,n){this.node=e,this.body=n}n.exports=t,t.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new r(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],19:[function(e,n){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],20:[function(e,n){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],21:[function(e,n){function t(e,n){function t(){return o(e,n,arguments)}return n=n||"Argument",{has:t}}function r(){function e(e,t){return o(e,t,n)}var n=arguments;return e}function o(e,n,t){if(void 0===e)throw new Error(n+" is not defined");for(var r=0;re)throw new Error("Invalid number of nodes");var n,t=l();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function r(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=t(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function o(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=l();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function i(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=l();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function a(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=l();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function u(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=l();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function s(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=l();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var u=i*e*n,s=r+o*e+u;r>0&&a.addLink(s,r-1+o*e+u),o>0&&a.addLink(s,r+(o-1)*e+u),i>0&&a.addLink(s,r+o*e+(i-1)*e*n)}return a}function f(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=l(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function c(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=l();for(n=0;e>n;++n)t.addNode(n);return t}function d(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,u=e("ngraph.random").random(o||42),s=l();for(i=0;n>i;++i)s.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,s.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(u.nextDouble()n)return!1;B(),_.splice(n,1);var t=f(e.fromId),o=f(e.toId);return t&&(n=r(e,t.links),n>=0&&t.links.splice(n,1)),o&&(n=r(e,o.links),n>=0&&o.links.splice(n,1)),U(e,"remove"),F(),!0}function h(e,n){var t,r=f(e);if(!r)return null;for(t=0;tn;++n)e(_[n])}function x(e,n,t){var r=f(e);return r&&r.links&&"function"==typeof n?t?b(r.links,e,n):w(r.links,e,n):void 0}function w(e,n,t){for(var r,o=0;o0&&(O.fire("changed",M),M.length=0)}function N(){return Object.keys?k:A}function k(e){if("function"==typeof e)for(var n=Object.keys(j),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function o(e){this.id=e,this.links=[],this.data=null}function i(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=t;var a=e("ngraph.events")},{"ngraph.events":6}],25:[function(e,n){function t(e,n){var r;if(e||(e={}),n)for(r in n)if(n.hasOwnProperty(r)){var o=e.hasOwnProperty(r),i=typeof n[r],a=!o||typeof e[r]!==i;a?e[r]=n[r]:"object"===i&&(e[r]=t(e[r],n[r]))}return e}n.exports=t},{}],26:[function(e,n){function t(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function r(e,n){var r=n||t();if("function"!=typeof r.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var t,o,i;for(t=e.length-1;t>0;--t)o=r.next(t+1),i=e[o],e[o]=e[t],e[t]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,t,o;for(n=e.length-1;n>0;--n)t=r.next(n+1),o=e[t],e[t]=e[n],e[n]=o;return e}}}n.exports={random:t,randomIterator:r}},{}],27:[function(e,n){function t(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=t},{}],28:[function(e,n){function t(e,n){var t=r(e);if(void 0===n)return t;for(var o=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},A=function(e){p=!1,r.off("touchmove",k),r.off("touchend",A),r.off("touchcancel",A),c=null,a&&a(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,r.on("touchmove",k),r.on("touchend",A),r.on("touchcancel",A)) -},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return a=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),r.off("mousemove",w),r.off("mouseup",E),r.off("touchmove",k),r.off("touchend",A),r.off("touchcancel",A),P(null)}}}n.exports=t;var r=e("../Utils/documentEvents.js"),o=e("../Utils/browserInfo.js"),i=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":40,"../Utils/documentEvents.js":41,"../Utils/findElementPosition.js":42}],37:[function(e,n){function t(e,n){var t=r(n),o=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){o=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(o);var r=i[e.id];return r&&r.onStart&&r.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(o),o=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(o){var t=i[o.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=t;var r=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":58}],38:[function(e,n){function t(e,n){function t(e){return d[e]}n=r(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var a=o(n.seed),u=new i(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(){return{x:a.next(n.maxX),y:a.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"==typeof y?y:!0}var d=30;n=n||{};var l,p,v,g=n.layout,h=n.graphics,m=n.container,y=void 0!==n.interactive?n.interactive:!0,x=!1,w=!0,b=0,E=0,L=!1,P=!1,N=!1,k={x:0,y:0},A={offsetX:0,offsetY:0,scale:1},j=function(){m=m||window.document.body,g=g||o(e,o.simulator({springLength:80,springCoeff:2e-4})),h=h||i(e,{container:m}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,l=(h.inputManager||u)(e,h)},_=r({}),I=function(){h.beginRender(),n.renderLinks&&h.renderLinks(),h.renderNodes(),h.endRender()},T=function(){return L=g.step()&&!P,I(),!L},C=function(e){return p?void(E+=e):void(e?(E+=e,p=s(function(){return T()},d)):(b=0,E=0,p=s(T,d)))},S=function(){N||(L=!1,p.restart())},D=function(){var e;if("number"==typeof n.prerender&&n.prerender>0)for(e=0;en,t)}),e.forEachNode(O),J(),e.on("changed",V)},Q=function(){x=!1,J(),H(),a.off("resize",W),_.off(),p.stop(),e.forEachLink(function(e){n.renderLinks&&F(e)}),e.forEachNode(function(e){G(e),R(e)}),g.dispose(),q()};return{run:function(e){return x||(j(),D(),M(),z(),K(),x=!0),C(e),this},reset:function(){h.resetScale(),M(),A.scale=1},pause:function(){N=!0,p.stop()},resume:function(){N=!1,p.restart()},rerender:function(){return I(),this},zoomOut:function(){return $(!0)},zoomIn:function(){return $(!1)},moveTo:function(e,n){h.graphCenterChanged(A.offsetX-e*A.scale,A.offsetY-n*A.scale),I()},getGraphics:function(){return h},dispose:function(){Q()},on:function(e,n){return _.addEventListener(e,n),this},off:function(e,n){return _.removeEventListener(e,n),this}}}n.exports=t;var r=e("ngraph.graph"),o=e("ngraph.forcelayout"),i=e("./svgGraphics.js"),a=e("../Utils/windowEvents.js"),u=e("../Input/domInputManager.js"),s=e("../Utils/timer.js"),f=e("../Utils/getDimensions.js"),c=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.forcelayout":7,"ngraph.graph":24}],50:[function(e,n){function t(){function e(){var e=r("svg");return n=r("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,a,u,s,f=1,c={},d={},l=function(){return r("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(){return r("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+a+","+u+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){a=e,u=n,w()},inputManager:i,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),s=n.getCTM().multiply(i);f=s.a,a=s.e,u=s.f;var c="matrix("+s.a+", 0, 0,"+s.d+","+s.e+","+s.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof s&&s(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):s=e),t},getSvgRoot:function(){return t}};return o(b),b}n.exports=t;var r=e("simplesvg"),o=e("ngraph.events"),i=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":35,"ngraph.events":6,simplesvg:28}],51:[function(e,n){function t(e){e=f(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,c,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=o(),P=i(),N=function(){return a()},k=function(){return u(3014898687)},A=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),c&&c.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(k=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:r,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,A()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],A()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,A(),I(this),y[0]},resetScale:function(){return j(),c&&(_(),A()),this},init:function(r){var o={};if(e.preserveDrawingBuffer&&(o.preserveDrawingBuffer=!0),n=r,_(),j(),n.appendChild(t),c=t.getContext("experimental-webgl",o),!c){var i="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(i),i}if(e.enableBlending&&(c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA),c.enable(c.BLEND)),e.clearColor){var a=e.clearColorValue;c.clearColor(a.r,a.g,a.b,a.a),this.beginRender=function(){c.clear(c.COLOR_BUFFER_BIT)}}L.load(c),L.updateSize(d/2,l/2),P.load(c),P.updateSize(d/2,l/2),A(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!c&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!c&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return s(T),T}n.exports=t;var r=e("../Input/webglInputManager.js"),o=e("../WebGL/webglLinkProgram.js"),i=e("../WebGL/webglNodeProgram.js"),a=e("../WebGL/webglSquare.js"),u=e("../WebGL/webglLine.js"),s=e("ngraph.events"),f=e("ngraph.merge")},{"../Input/webglInputManager.js":37,"../WebGL/webglLine.js":59,"../WebGL/webglLinkProgram.js":60,"../WebGL/webglNodeProgram.js":61,"../WebGL/webglSquare.js":62,"ngraph.events":6,"ngraph.merge":25}],52:[function(e,n){function t(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=t},{}],53:[function(e,n){function t(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=t},{}],54:[function(e,n){function t(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function i(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function o(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=t},{}],55:[function(e,n){function t(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!r(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:i,getCoordinates:a,load:u};return E}function r(e){return 0===(e&e-1)}var o=e("./texture.js");n.exports=t},{"./texture.js":53}],56:[function(e,n){function t(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=t},{}],57:[function(e,n){function t(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=r(),k=o(),A=1024,j=0,_=new Float32Array(64);return{load:t,position:u,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function r(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function o(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var i=e("./webglAtlas.js"),a=e("./webgl.js");n.exports=t},{"./webgl.js":54,"./webglAtlas.js":55}],58:[function(e,n){function t(e){function n(){x=null}function t(e){x=e}function o(e){return"function"==typeof e&&k.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(k,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],k=[],A=e.getGraphicsRoot();h(A);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:o,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var r=e("../Utils/documentEvents.js");n.exports=t},{"../Utils/documentEvents.js":41}],59:[function(e,n){function t(e){return{color:r(e)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],60:[function(e,n){function t(){var e,n,t,o,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,o=r(a),e=o.createProgram(v,p),n.useProgram(e),i=o.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&o.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&o.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],61:[function(e,n){function t(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=r(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function o(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(N,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:o,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],62:[function(e,n){function t(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],63:[function(e,n){n.exports="0.7.7"},{}]},{},[1])(1)}); \ No newline at end of file +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-s*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=t},{}],3:[function(e,n){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n){function t(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function g(e){var n=w[e];n.mass=y(e)}function h(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function m(e){var n=w[e];return n||(c(e),n=w[e]),n}function y(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var x=e("ngraph.physics.simulator");t=t||x(),o(t,"physicsSimulator").has("step","getBestNewBodyPosition","addBodyAt");var w="function"==typeof Object.create?Object.create(null):{},b={},E=t.settings.springTransform||r;f(),u();var L={step:function(){return t.step()},getNodePosition:function(e){return m(e).pos},setNodePosition:function(e){var n=m(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return t.getBBox()},pinNode:function(e,n){var t=m(e.id);t.isPinned=!!n},isNodePinned:function(e){return m(e.id).isPinned},dispose:function(){n.off("changed",s)},getBody:a,getSpring:i,simulator:t};return L}function r(){}n.exports=t,n.exports.simulator=e("ngraph.physics.simulator");var o=e("varta")},{"ngraph.physics.simulator":8,varta:21}],8:[function(e,n){function t(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.force.reset(),v.updateBodyForce(e),m.update(e);for(n=p.length;n--;)h.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),u=n.createBounds||e("./lib/bounds"),s=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),g=u(l,n),h=f(n),m=s(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return g.update(),en))return l.splice(n,1),0===l.length&&g.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return g.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=t},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":25,"ngraph.quadtreebh":17}],9:[function(e,n){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;ut;++t){var s=e[t],f=n/s.mass;s.velocity.x+=f*s.force.x,s.velocity.y+=f*s.force.y;var c=s.velocity.x,d=s.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=t},{}],13:[function(e,n){function t(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=t},{}],14:[function(e,n){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":25,"ngraph.random":26}],15:[function(e,n){function t(e,n,t){var o="[object Array]"===Object.prototype.toString.call(t);if(o)for(var i=0;i0&&u(s.pos,a.pos));if(0===f&&u(s.pos,a.pos))return}c.push(i,s),c.push(i,a)}else{var h=a.pos.x,m=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*h,i.massY=i.massY+a.mass*m;var y=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;if(h>w){y+=1;var L=x;x=w,w+=w-L}if(m>E){y+=2;var P=b;b=E,E+=E-P}var N=t(i,y);N?c.push(N,a):(N=v(),N.left=x,N.top=b,N.right=w,N.bottom=E,N.body=a,r(i,y,N))}}},m=function(e){var n,t,r,i,a=f,u=0,c=0,l=1,p=0,v=1;for(a[0]=g;l;){var h=a[p],m=h.body;l-=1,p+=1;var y=m!==e;m&&y?(t=m.pos.x-e.pos.x,r=m.pos.y-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),n=s*m.mass*e.mass/(i*i*i),u+=n*t,c+=n*r):y&&(t=h.massX/h.mass-e.pos.x,r=h.massY/h.mass-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),(h.right-h.left)/iu&&(t=u),u>o&&(o=u),r>s&&(r=s),s>i&&(i=s)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,p=0,g=v(),g.left=t,g.right=o,g.top=r,g.bottom=i,n=a-1,n>0&&(g.body=e[n]);n--;)h(e[n],g)};return{insertBodies:y,updateBodyForce:m,options:function(e){return e?("number"==typeof e.gravity&&(s=e.gravity),"number"==typeof e.theta&&(d=e.theta),this):{gravity:s,theta:d}}}}},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":26}],18:[function(e,n){function t(){this.stack=[],this.popIdx=0}function r(e,n){this.node=e,this.body=n}n.exports=t,t.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new r(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],19:[function(e,n){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],20:[function(e,n){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],21:[function(e,n){function t(e,n){function t(){return o(e,n,arguments)}return n=n||"Argument",{has:t}}function r(){function e(e,t){return o(e,t,n)}var n=arguments;return e}function o(e,n,t){if(void 0===e)throw new Error(n+" is not defined");for(var r=0;re)throw new Error("Invalid number of nodes");var n,t=l();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function r(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=t(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function o(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=l();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function i(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=l();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function a(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=l();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function u(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=l();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function s(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=l();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var u=i*e*n,s=r+o*e+u;r>0&&a.addLink(s,r-1+o*e+u),o>0&&a.addLink(s,r+(o-1)*e+u),i>0&&a.addLink(s,r+o*e+(i-1)*e*n)}return a}function f(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=l(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function c(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=l();for(n=0;e>n;++n)t.addNode(n);return t}function d(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,u=e("ngraph.random").random(o||42),s=l();for(i=0;n>i;++i)s.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,s.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(u.nextDouble()n)return!1;B(),_.splice(n,1);var t=f(e.fromId),o=f(e.toId);return t&&(n=r(e,t.links),n>=0&&t.links.splice(n,1)),o&&(n=r(e,o.links),n>=0&&o.links.splice(n,1)),U(e,"remove"),F(),!0}function h(e,n){var t,r=f(e);if(!r)return null;for(t=0;tn;++n)e(_[n])}function x(e,n,t){var r=f(e);return r&&r.links&&"function"==typeof n?t?b(r.links,e,n):w(r.links,e,n):void 0}function w(e,n,t){for(var r,o=0;o0&&(O.fire("changed",M),M.length=0)}function N(){return Object.keys?k:A}function k(e){if("function"==typeof e)for(var n=Object.keys(j),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function o(e){this.id=e,this.links=[],this.data=null}function i(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=t;var a=e("ngraph.events")},{"ngraph.events":6}],25:[function(e,n){function t(e,n){var r;if(e||(e={}),n)for(r in n)if(n.hasOwnProperty(r)){var o=e.hasOwnProperty(r),i=typeof n[r],a=!o||typeof e[r]!==i;a?e[r]=n[r]:"object"===i&&(e[r]=t(e[r],n[r]))}return e}n.exports=t},{}],26:[function(e,n){function t(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function r(e,n){var r=n||t();if("function"!=typeof r.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var t,o,i;for(t=e.length-1;t>0;--t)o=r.next(t+1),i=e[o],e[o]=e[t],e[t]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,t,o;for(n=e.length-1;n>0;--n)t=r.next(n+1),o=e[t],e[t]=e[n],e[n]=o;return e}}}n.exports={random:t,randomIterator:r}},{}],27:[function(e,n){function t(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=t},{}],28:[function(e,n){function t(e,n){var t=r(e);if(void 0===n)return t;for(var o=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},A=function(e){p=!1,r.off("touchmove",k),r.off("touchend",A),r.off("touchcancel",A),c=null,a&&a(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,r.on("touchmove",k),r.on("touchend",A),r.on("touchcancel",A)) +},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return a=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),r.off("mousemove",w),r.off("mouseup",E),r.off("touchmove",k),r.off("touchend",A),r.off("touchcancel",A),P(null)}}}n.exports=t;var r=e("../Utils/documentEvents.js"),o=e("../Utils/browserInfo.js"),i=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":40,"../Utils/documentEvents.js":41,"../Utils/findElementPosition.js":42}],37:[function(e,n){function t(e,n){var t=r(n),o=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){o=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(o);var r=i[e.id];return r&&r.onStart&&r.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(o),o=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(o){var t=i[o.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=t;var r=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":58}],38:[function(e,n){function t(e,n){function t(e){return d[e]}n=r(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var a=o(n.seed),u=new i(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(){return{x:a.next(n.maxX),y:a.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"==typeof z?z:!0}function d(){G=G||window.document.body,F=F||o(e,o.simulator({springLength:80,springCoeff:2e-4})),O=O||i(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||u)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=s(function(){return p()},M)):(X=0,V=0,R=s(p,M)))}function g(){J||(W=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;en,t)}),e.forEachNode(E),T(),e.on("changed",j)}function D(){q=!1,T(),I(),a.off("resize",_),Q.off(),R.stop(),e.forEachLink(function(e){n.renderLinks&&b(e)}),e.forEachNode(function(e){L(e),x(e)}),F.dispose(),N()}var M=30;n=n||{};var U,R,B,F=n.layout,O=n.graphics,G=n.container,z=void 0!==n.interactive?n.interactive:!0,q=!1,Y=!0,X=0,V=0,W=!1,H=!1,J=!1,$={x:0,y:0},K={offsetX:0,offsetY:0,scale:1},Q=r({});return{run:function(e){return q||(d(),h(),m(),P(),S(),q=!0),v(e),this},reset:function(){O.resetScale(),m(),K.scale=1},pause:function(){J=!0,R.stop()},resume:function(){J=!1,R.restart()},rerender:function(){return l(),this},zoomOut:function(){return C(!0)},zoomIn:function(){return C(!1)},moveTo:function(e,n){O.graphCenterChanged(K.offsetX-e*K.scale,K.offsetY-n*K.scale),l()},getGraphics:function(){return O},dispose:function(){D()},on:function(e,n){return Q.addEventListener(e,n),this},off:function(e,n){return Q.removeEventListener(e,n),this}}}n.exports=t;var r=e("ngraph.graph"),o=e("ngraph.forcelayout"),i=e("./svgGraphics.js"),a=e("../Utils/windowEvents.js"),u=e("../Input/domInputManager.js"),s=e("../Utils/timer.js"),f=e("../Utils/getDimensions.js"),c=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.forcelayout":7,"ngraph.graph":24}],50:[function(e,n){function t(){function e(){var e=r("svg");return n=r("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,a,u,s,f=1,c={},d={},l=function(){return r("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(){return r("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+a+","+u+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){a=e,u=n,w()},inputManager:i,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),s=n.getCTM().multiply(i);f=s.a,a=s.e,u=s.f;var c="matrix("+s.a+", 0, 0,"+s.d+","+s.e+","+s.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof s&&s(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):s=e),t},getSvgRoot:function(){return t}};return o(b),b}n.exports=t;var r=e("simplesvg"),o=e("ngraph.events"),i=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":35,"ngraph.events":6,simplesvg:28}],51:[function(e,n){function t(e){e=f(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,c,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=o(),P=i(),N=function(){return a()},k=function(){return u(3014898687)},A=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),c&&c.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(k=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:r,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,A()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],A()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,A(),I(this),y[0]},resetScale:function(){return j(),c&&(_(),A()),this},init:function(r){var o={};if(e.preserveDrawingBuffer&&(o.preserveDrawingBuffer=!0),n=r,_(),j(),n.appendChild(t),c=t.getContext("experimental-webgl",o),!c){var i="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(i),i}if(e.enableBlending&&(c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA),c.enable(c.BLEND)),e.clearColor){var a=e.clearColorValue;c.clearColor(a.r,a.g,a.b,a.a),this.beginRender=function(){c.clear(c.COLOR_BUFFER_BIT)}}L.load(c),L.updateSize(d/2,l/2),P.load(c),P.updateSize(d/2,l/2),A(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!c&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!c&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return s(T),T}n.exports=t;var r=e("../Input/webglInputManager.js"),o=e("../WebGL/webglLinkProgram.js"),i=e("../WebGL/webglNodeProgram.js"),a=e("../WebGL/webglSquare.js"),u=e("../WebGL/webglLine.js"),s=e("ngraph.events"),f=e("ngraph.merge")},{"../Input/webglInputManager.js":37,"../WebGL/webglLine.js":59,"../WebGL/webglLinkProgram.js":60,"../WebGL/webglNodeProgram.js":61,"../WebGL/webglSquare.js":62,"ngraph.events":6,"ngraph.merge":25}],52:[function(e,n){function t(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=t},{}],53:[function(e,n){function t(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=t},{}],54:[function(e,n){function t(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function i(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function o(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=t},{}],55:[function(e,n){function t(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!r(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:i,getCoordinates:a,load:u};return E}function r(e){return 0===(e&e-1)}var o=e("./texture.js");n.exports=t},{"./texture.js":53}],56:[function(e,n){function t(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=t},{}],57:[function(e,n){function t(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=r(),k=o(),A=1024,j=0,_=new Float32Array(64);return{load:t,position:u,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function r(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function o(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var i=e("./webglAtlas.js"),a=e("./webgl.js");n.exports=t},{"./webgl.js":54,"./webglAtlas.js":55}],58:[function(e,n){function t(e){function n(){x=null}function t(e){x=e}function o(e){return"function"==typeof e&&k.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(k,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],k=[],A=e.getGraphicsRoot();h(A);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:o,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var r=e("../Utils/documentEvents.js");n.exports=t},{"../Utils/documentEvents.js":41}],59:[function(e,n){function t(e){return{color:r(e)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],60:[function(e,n){function t(){var e,n,t,o,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,o=r(a),e=o.createProgram(v,p),n.useProgram(e),i=o.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&o.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&o.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],61:[function(e,n){function t(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=r(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function o(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(N,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:o,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],62:[function(e,n){function t(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],63:[function(e,n){n.exports="0.7.8"},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/package.json b/package.json index 3e70ae5..e24b5ec 100644 --- a/package.json +++ b/package.json @@ -33,15 +33,15 @@ }, "dependencies": { "gintersect": "0.1.0", - "ngraph.centrality": "0.1.2", + "ngraph.centrality": "0.1.3", "ngraph.events": "0.0.3", - "ngraph.forcelayout": "0.0.17", - "ngraph.fromjson": "0.1.6", - "ngraph.generators": "0.0.14", - "ngraph.graph": "0.0.10", + "ngraph.forcelayout": "0.0.18", + "ngraph.fromjson": "0.1.7", + "ngraph.generators": "0.0.15", + "ngraph.graph": "0.0.11", "ngraph.merge": "0.0.1", "ngraph.random": "0.0.1", - "ngraph.tojson": "0.1.2", + "ngraph.tojson": "0.1.3", "simplesvg": "0.0.10" } } diff --git a/src/version.js b/src/version.js index 51d3684..032d133 100644 --- a/src/version.js +++ b/src/version.js @@ -1,2 +1,2 @@ // todo: this should be generated at build time. -module.exports = '0.7.7'; +module.exports = '0.7.8'; From afb97598a6a541c211b74202eca99bc637c44712 Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 8 Apr 2015 20:30:37 -0700 Subject: [PATCH 190/276] 0.7.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e24b5ec..ef96717 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.7.7", + "version": "0.7.8", "description": "Graph Drawing Library", "main": "src/viva", "directories": { From 7b69dfaf2cb0a4e9d4c621fc68c34a6bf9cc6faf Mon Sep 17 00:00:00 2001 From: ahmet kizilay Date: Thu, 9 Apr 2015 16:44:48 +0300 Subject: [PATCH 191/276] fixed wrong js loading for eventify and publicEvents event methods #134 There was a bug with setting the eventify variable on `renderer.js`. Instead of ngraph.events, the variable is set from the `ngraph.graph` After this fix, publicEvents object has on and off methods to register events. event registration methods for the renderer erroneously uses `publicEvents.addEventListener` and `publicEvents.removeEventListener` method. changed the method name to `on` and `off`, respectively. --- dist/vivagraph.js | 3348 ++++++++++++++++++++--------------------- dist/vivagraph.min.js | 2 +- src/View/renderer.js | 6 +- 3 files changed, 1678 insertions(+), 1678 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 0299416..fecca6b 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -1,120 +1,120 @@ !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Viva=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= 0; - } else if (typeof interactive === 'boolean') { - return interactive; - } - return true; // default setting - } - - function prepareSettings() { - container = container || window.document.body; - layout = layout || forceDirected(graph, forceDirected.simulator({ - springLength: 80, - springCoeff: 0.0002, - })); - graphics = graphics || svgGraphics(graph, { - container: container - }); - - if (!settings.hasOwnProperty('renderLinks')) { - settings.renderLinks = true; - } - - settings.prerender = settings.prerender || 0; - inputManager = (graphics.inputManager || domInputManager)(graph, graphics); - } - - function renderGraph() { - graphics.beginRender(); - - // todo: move this check graphics - if (settings.renderLinks) { - graphics.renderLinks(); - } - graphics.renderNodes(); - graphics.endRender(); - } - - function onRenderFrame() { - isStable = layout.step() && !userInteraction; - renderGraph(); - - return !isStable; - } - - function renderIterations(iterationsCount) { - if (animationTimer) { - totalIterationsCount += iterationsCount; - return; - } - - if (iterationsCount) { - totalIterationsCount += iterationsCount; - - animationTimer = timer(function() { - return onRenderFrame(); - }, FRAME_INTERVAL); - } else { - currentStep = 0; - totalIterationsCount = 0; - animationTimer = timer(onRenderFrame, FRAME_INTERVAL); - } - } - - function resetStable() { - if (isPaused) { - return; - } - - isStable = false; - animationTimer.restart(); - } - - function prerender() { - // To get good initial positions for the graph - // perform several prerender steps in background. - if (typeof settings.prerender === 'number' && settings.prerender > 0) { - for (var i = 0; i < settings.prerender; i += 1) { - layout.step(); - } - } - } - - function updateCenter() { - var graphRect = layout.getGraphRect(), - containerSize = getDimension(container); - - viewPortOffset.x = viewPortOffset.y = 0; - transform.offsetX = containerSize.width / 2 - (graphRect.x2 + graphRect.x1) / 2; - transform.offsetY = containerSize.height / 2 - (graphRect.y2 + graphRect.y1) / 2; - graphics.graphCenterChanged(transform.offsetX, transform.offsetY); - - updateCenterRequired = false; - } - - function createNodeUi(node) { - var nodePosition = layout.getNodePosition(node.id); - graphics.addNode(node, nodePosition); - } - - function removeNodeUi(node) { - graphics.releaseNode(node); - } - - function createLinkUi(link) { - var linkPosition = layout.getLinkPosition(link.id); - graphics.addLink(link, linkPosition); - } - - function removeLinkUi(link) { - graphics.releaseLink(link); - } - - function listenNodeEvents(node) { - if (!isInteractive('node')) { - return; - } - - var wasPinned = false; - - // TODO: This may not be memory efficient. Consider reusing handlers object. - inputManager.bindDragNDrop(node, { - onStart: function() { - wasPinned = layout.isNodePinned(node); - layout.pinNode(node, true); - userInteraction = true; - resetStable(); - }, - onDrag: function(e, offset) { - var oldPos = layout.getNodePosition(node.id); - layout.setNodePosition(node.id, - oldPos.x + offset.x / transform.scale, - oldPos.y + offset.y / transform.scale); - - userInteraction = true; - - renderGraph(); - }, - onStop: function() { - layout.pinNode(node, wasPinned); - userInteraction = false; - } - }); - } - - function releaseNodeEvents(node) { - inputManager.bindDragNDrop(node, null); - } - - function initDom() { - graphics.init(container); - - graph.forEachNode(createNodeUi); - - if (settings.renderLinks) { - graph.forEachLink(createLinkUi); - } - } - - function releaseDom() { - graphics.release(container); - } - - function processNodeChange(change) { - var node = change.node; - - if (change.changeType === 'add') { - createNodeUi(node); - listenNodeEvents(node); - if (updateCenterRequired) { - updateCenter(); - } - } else if (change.changeType === 'remove') { - releaseNodeEvents(node); - removeNodeUi(node); - if (graph.getNodesCount() === 0) { - updateCenterRequired = true; // Next time when node is added - center the graph. - } - } else if (change.changeType === 'update') { - releaseNodeEvents(node); - removeNodeUi(node); - - createNodeUi(node); - listenNodeEvents(node); - } - } - - function processLinkChange(change) { - var link = change.link; - if (change.changeType === 'add') { - if (settings.renderLinks) { - createLinkUi(link); - } - } else if (change.changeType === 'remove') { - if (settings.renderLinks) { - removeLinkUi(link); - } - } else if (change.changeType === 'update') { - throw 'Update type is not implemented. TODO: Implement me!'; - } - } - - function onGraphChanged(changes) { - var i, change; - for (i = 0; i < changes.length; i += 1) { - change = changes[i]; - if (change.node) { - processNodeChange(change); - } else if (change.link) { - processLinkChange(change); - } - } - - resetStable(); - } - - function onWindowResized() { - updateCenter(); - onRenderFrame(); - } - - function releaseContainerDragManager() { - if (containerDrag) { - containerDrag.release(); - containerDrag = null; - } - } - - function releaseGraphEvents() { - graph.off('changed', onGraphChanged); - } - - function scale(out, scrollPoint) { - if (!scrollPoint) { - var containerSize = getDimension(container); - scrollPoint = { - x: containerSize.width / 2, - y: containerSize.height / 2 - }; - } - var scaleFactor = Math.pow(1 + 0.4, out ? -0.2 : 0.2); - transform.scale = graphics.scale(scaleFactor, scrollPoint); - - renderGraph(); - publicEvents.fire('scale', transform.scale); - - return transform.scale; - } - - function listenToEvents() { - windowEvents.on('resize', onWindowResized); - - releaseContainerDragManager(); - if (isInteractive('drag')) { - containerDrag = dragndrop(container); - containerDrag.onDrag(function(e, offset) { - viewPortOffset.x += offset.x; - viewPortOffset.y += offset.y; - graphics.translateRel(offset.x, offset.y); - - renderGraph(); - }); - } - - if (isInteractive('scroll')) { - containerDrag.onScroll(function(e, scaleOffset, scrollPoint) { - scale(scaleOffset < 0, scrollPoint); - }); - } - - graph.forEachNode(listenNodeEvents); - - releaseGraphEvents(); - graph.on('changed', onGraphChanged); - } - - function stopListenToEvents() { - rendererInitialized = false; - releaseGraphEvents(); - releaseContainerDragManager(); - windowEvents.off('resize', onWindowResized); - publicEvents.off(); - animationTimer.stop(); - - graph.forEachLink(function(link) { - if (settings.renderLinks) { - removeLinkUi(link); - } - }); - - graph.forEachNode(function(node) { - releaseNodeEvents(node); - removeNodeUi(node); - }); - - layout.dispose(); - releaseDom(); - } -} - -},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.forcelayout":7,"ngraph.graph":24}],50:[function(require,module,exports){ -/** - * @fileOverview Defines a graph renderer that uses SVG based drawings. - * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com - */ - -module.exports = svgGraphics; - -var svg = require('simplesvg'); -var eventify = require('ngraph.events'); -var domInputManager = require('../Input/domInputManager.js'); - -/** - * Performs svg-based graph rendering. This module does not perform - * layout, but only visualizes nodes and edges of the graph. - */ -function svgGraphics() { - var svgContainer, - svgRoot, - offsetX, - offsetY, - initCallback, - actualScale = 1, - allNodes = {}, - allLinks = {}, -/*jshint unused: false */ - nodeBuilder = function (node) { - return svg("rect") - .attr("width", 10) - .attr("height", 10) - .attr("fill", "#00a2e8"); - }, - - nodePositionCallback = function (nodeUI, pos) { - // TODO: Remove magic 5. It should be half of the width or height of the node. - nodeUI.attr("x", pos.x - 5) - .attr("y", pos.y - 5); - }, - - linkBuilder = function (link) { - return svg("line").attr("stroke", "#999"); - }, - - linkPositionCallback = function (linkUI, fromPos, toPos) { - linkUI.attr("x1", fromPos.x) - .attr("y1", fromPos.y) - .attr("x2", toPos.x) - .attr("y2", toPos.y); - }, - - fireRescaled = function (graphics) { - // TODO: maybe we shall copy changes? - graphics.fire("rescaled"); - }, - - cachedPos = {x : 0, y: 0}, - cachedFromPos = {x : 0, y: 0}, - cachedToPos = {x : 0, y: 0}, - - updateTransform = function () { - if (svgContainer) { - var transform = "matrix(" + actualScale + ", 0, 0," + actualScale + "," + offsetX + "," + offsetY + ")"; - svgContainer.attr("transform", transform); - } - }; - - svgRoot = createSvgRoot(); - - var graphics = { - getNodeUI: function (nodeId) { - return allNodes[nodeId]; - }, - - getLinkUI: function (linkId) { - return allLinks[linkId]; - }, - - /** - * Sets the callback that creates node representation. - * - * @param builderCallback a callback function that accepts graph node - * as a parameter and must return an element representing this node. - * - * @returns If builderCallbackOrNode is a valid callback function, instance of this is returned; - * Otherwise undefined value is returned - */ - node : function (builderCallback) { - if (typeof builderCallback !== "function") { - return; // todo: throw? This is not compatible with old versions - } - - nodeBuilder = builderCallback; - - return this; - }, - - /** - * Sets the callback that creates link representation - * - * @param builderCallback a callback function that accepts graph link - * as a parameter and must return an element representing this link. - * - * @returns If builderCallback is a valid callback function, instance of this is returned; - * Otherwise undefined value is returned. - */ - link : function (builderCallback) { - if (typeof builderCallback !== "function") { - return; // todo: throw? This is not compatible with old versions - } - - linkBuilder = builderCallback; - return this; - }, - - /** - * Allows to override default position setter for the node with a new - * function. newPlaceCallback(nodeUI, position, node) is function which - * is used by updateNodePosition(). - */ - placeNode : function (newPlaceCallback) { - nodePositionCallback = newPlaceCallback; - return this; - }, - - placeLink : function (newPlaceLinkCallback) { - linkPositionCallback = newPlaceLinkCallback; - return this; - }, - - /** - * Called every before renderer starts rendering. - */ - beginRender : function () {}, - - /** - * Called every time when renderer finishes one step of rendering. - */ - endRender : function () {}, - - /** - * Sets translate operation that should be applied to all nodes and links. - */ - graphCenterChanged : function (x, y) { - offsetX = x; - offsetY = y; - updateTransform(); - }, - - /** - * Default input manager listens to DOM events to process nodes drag-n-drop - */ - inputManager : domInputManager, - - translateRel : function (dx, dy) { - var p = svgRoot.createSVGPoint(), - t = svgContainer.getCTM(), - origin = svgRoot.createSVGPoint().matrixTransform(t.inverse()); - - p.x = dx; - p.y = dy; - - p = p.matrixTransform(t.inverse()); - p.x = (p.x - origin.x) * t.a; - p.y = (p.y - origin.y) * t.d; - - t.e += p.x; - t.f += p.y; - - var transform = "matrix(" + t.a + ", 0, 0," + t.d + "," + t.e + "," + t.f + ")"; - svgContainer.attr("transform", transform); - }, - - scale : function (scaleFactor, scrollPoint) { - var p = svgRoot.createSVGPoint(); - p.x = scrollPoint.x; - p.y = scrollPoint.y; - - p = p.matrixTransform(svgContainer.getCTM().inverse()); // translate to SVG coordinates - - // Compute new scale matrix in current mouse position - var k = svgRoot.createSVGMatrix().translate(p.x, p.y).scale(scaleFactor).translate(-p.x, -p.y), - t = svgContainer.getCTM().multiply(k); - - actualScale = t.a; - offsetX = t.e; - offsetY = t.f; - var transform = "matrix(" + t.a + ", 0, 0," + t.d + "," + t.e + "," + t.f + ")"; - svgContainer.attr("transform", transform); - - fireRescaled(this); - return actualScale; - }, - - resetScale : function () { - actualScale = 1; - var transform = "matrix(1, 0, 0, 1, 0, 0)"; - svgContainer.attr("transform", transform); - fireRescaled(this); - return this; - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render. - */ - init : function (container) { - container.appendChild(svgRoot); - updateTransform(); - // Notify the world if someone waited for update. TODO: should send an event - if (typeof initCallback === "function") { - initCallback(svgRoot); - } - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider release occupied resources. - */ - release : function (container) { - if (svgRoot && container) { - container.removeChild(svgRoot); - } - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render given link of the graph - * - * @param link - model of a link - */ - addLink: function (link, pos) { - var linkUI = linkBuilder(link); - if (!linkUI) { return; } - linkUI.position = pos; - linkUI.link = link; - allLinks[link.id] = linkUI; - if (svgContainer.childElementCount > 0) { - svgContainer.insertBefore(linkUI, svgContainer.firstChild); - } else { - svgContainer.appendChild(linkUI); - } - return linkUI; - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider remove link from rendering surface. - * - * @param linkUI visual representation of the link created by link() execution. - **/ - releaseLink : function (link) { - var linkUI = allLinks[link.id]; - if (linkUI) { - svgContainer.removeChild(linkUI); - delete allLinks[link.id]; - } - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render given node of the graph. - * - * @param nodeUI visual representation of the node created by node() execution. - **/ - addNode : function (node, pos) { - var nodeUI = nodeBuilder(node); - if (!nodeUI) { - return; - } - nodeUI.position = pos; - nodeUI.node = node; - allNodes[node.id] = nodeUI; - - svgContainer.appendChild(nodeUI); - - return nodeUI; - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider remove node from rendering surface. - * - * @param node graph's node - **/ - releaseNode : function (node) { - var nodeUI = allNodes[node.id]; - if (nodeUI) { - svgContainer.removeChild(nodeUI); - delete allNodes[node.id]; - } - }, - - renderNodes : function () { - for (var key in allNodes) { - if (allNodes.hasOwnProperty(key)) { - var nodeUI = allNodes[key]; - cachedPos.x = nodeUI.position.x; - cachedPos.y = nodeUI.position.y; - nodePositionCallback(nodeUI, cachedPos, nodeUI.node); - } - } - }, - - renderLinks : function () { - for (var key in allLinks) { - if (allLinks.hasOwnProperty(key)) { - var linkUI = allLinks[key]; - cachedFromPos.x = linkUI.position.from.x; - cachedFromPos.y = linkUI.position.from.y; - cachedToPos.x = linkUI.position.to.x; - cachedToPos.y = linkUI.position.to.y; - linkPositionCallback(linkUI, cachedFromPos, cachedToPos, linkUI.link); - } - } - }, - - /** - * Returns root element which hosts graphics. - */ - getGraphicsRoot : function (callbackWhenReady) { - // todo: should fire an event, instead of having this context. - if (typeof callbackWhenReady === "function") { - if (svgRoot) { - callbackWhenReady(svgRoot); - } else { - initCallback = callbackWhenReady; - } - } - return svgRoot; - }, - /** - * Returns root SVG element. - * - * Note: This is internal method specific to this renderer - */ - getSvgRoot : function () { - return svgRoot; - } - }; - - - // Let graphics fire events before we return it to the caller. - eventify(graphics); - - return graphics; - - function createSvgRoot() { - var svgRoot = svg("svg"); - - svgContainer = svg("g") - .attr("buffered-rendering", "dynamic"); - - svgRoot.appendChild(svgContainer); - return svgRoot; - } -} +/** + * @fileOverview Defines a graph renderer that uses CSS based drawings. + * + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka + */ -},{"../Input/domInputManager.js":35,"ngraph.events":6,"simplesvg":28}],51:[function(require,module,exports){ -/** - * @fileOverview Defines a graph renderer that uses WebGL based drawings. - * - * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka - */ - -module.exports = webglGraphics; - -var webglInputManager = require('../Input/webglInputManager.js'); -var webglLinkProgram = require('../WebGL/webglLinkProgram.js'); -var webglNodeProgram = require('../WebGL/webglNodeProgram.js'); -var webglSquare = require('../WebGL/webglSquare.js'); -var webglLine = require('../WebGL/webglLine.js'); -var eventify = require('ngraph.events'); -var merge = require('ngraph.merge'); - -/** - * Performs webgl-based graph rendering. This module does not perform - * layout, but only visualizes nodes and edges of the graph. - * - * @param options - to customize graphics behavior. Currently supported parameter - * enableBlending - true by default, allows to use transparency in node/links colors. - * preserveDrawingBuffer - false by default, tells webgl to preserve drawing buffer. - * See https://www.khronos.org/registry/webgl/specs/1.0/#5.2 - */ - -function webglGraphics(options) { - options = merge(options, { - enableBlending : true, - preserveDrawingBuffer : false, - clearColor: false, - clearColorValue : { - r : 1, - g : 1, - b : 1, - a : 1 - } - }); - - var container, - graphicsRoot, - gl, - width, - height, - nodesCount = 0, - linksCount = 0, - transform = [ - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - ], - userPlaceNodeCallback, - userPlaceLinkCallback, - nodes = [], - links = [], - initCallback, - - allNodes = {}, - allLinks = {}, - linkProgram = webglLinkProgram(), - nodeProgram = webglNodeProgram(), -/*jshint unused: false */ - nodeUIBuilder = function (node) { - return webglSquare(); // Just make a square, using provided gl context (a nodeProgram); - }, - - linkUIBuilder = function (link) { - return webglLine(0xb3b3b3ff); - }, -/*jshint unused: true */ - updateTransformUniform = function () { - linkProgram.updateTransform(transform); - nodeProgram.updateTransform(transform); - }, - - resetScaleInternal = function () { - transform = [1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1]; - }, - - updateSize = function () { - if (container && graphicsRoot) { - width = graphicsRoot.width = Math.max(container.offsetWidth, 1); - height = graphicsRoot.height = Math.max(container.offsetHeight, 1); - if (gl) { gl.viewport(0, 0, width, height); } - if (linkProgram) { linkProgram.updateSize(width / 2, height / 2); } - if (nodeProgram) { nodeProgram.updateSize(width / 2, height / 2); } - } - }, - - fireRescaled = function (graphics) { - graphics.fire("rescaled"); - }; - - graphicsRoot = window.document.createElement("canvas"); - - var graphics = { - getLinkUI: function (linkId) { - return allLinks[linkId]; - }, - - getNodeUI: function (nodeId) { - return allNodes[nodeId]; - }, - - /** - * Sets the callback that creates node representation. - * - * @param builderCallback a callback function that accepts graph node - * as a parameter and must return an element representing this node. - * - * @returns If builderCallbackOrNode is a valid callback function, instance of this is returned; - * Otherwise undefined value is returned - */ - node : function (builderCallback) { - if (typeof builderCallback !== "function") { - return; // todo: throw? This is not compatible with old versions - } - - nodeUIBuilder = builderCallback; - - return this; - }, - - /** - * Sets the callback that creates link representation - * - * @param builderCallback a callback function that accepts graph link - * as a parameter and must return an element representing this link. - * - * @returns If builderCallback is a valid callback function, instance of this is returned; - * Otherwise undefined value is returned. - */ - link : function (builderCallback) { - if (typeof builderCallback !== "function") { - return; // todo: throw? This is not compatible with old versions - } - - linkUIBuilder = builderCallback; - return this; - }, - - - /** - * Allows to override default position setter for the node with a new - * function. newPlaceCallback(nodeUI, position) is function which - * is used by updateNodePosition(). - */ - placeNode : function (newPlaceCallback) { - userPlaceNodeCallback = newPlaceCallback; - return this; - }, - - placeLink : function (newPlaceLinkCallback) { - userPlaceLinkCallback = newPlaceLinkCallback; - return this; - }, - - /** - * Custom input manager listens to mouse events to process nodes drag-n-drop inside WebGL canvas - */ - inputManager : webglInputManager, - - /** - * Called every time before renderer starts rendering. - */ - beginRender : function () { - // this function could be replaced by this.init, - // based on user options. - }, - - /** - * Called every time when renderer finishes one step of rendering. - */ - endRender : function () { - if (linksCount > 0) { - linkProgram.render(); - } - if (nodesCount > 0) { - nodeProgram.render(); - } - }, - - bringLinkToFront : function (linkUI) { - var frontLinkId = linkProgram.getFrontLinkId(), - srcLinkId, - temp; - - linkProgram.bringToFront(linkUI); - - if (frontLinkId > linkUI.id) { - srcLinkId = linkUI.id; - - temp = links[frontLinkId]; - links[frontLinkId] = links[srcLinkId]; - links[frontLinkId].id = frontLinkId; - links[srcLinkId] = temp; - links[srcLinkId].id = srcLinkId; - } - }, - - /** - * Sets translate operation that should be applied to all nodes and links. - */ - graphCenterChanged : function (x, y) { - transform[12] = (2 * x / width) - 1; - transform[13] = 1 - (2 * y / height); - updateTransformUniform(); - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render given link of the graph - * - * @param link - model of a link - */ - addLink: function (link, boundPosition) { - var uiid = linksCount++, - ui = linkUIBuilder(link); - ui.id = uiid; - ui.pos = boundPosition; - - linkProgram.createLink(ui); - - links[uiid] = ui; - allLinks[link.id] = ui; - return ui; - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render given node of the graph. - * - * @param nodeUI visual representation of the node created by node() execution. - **/ - addNode : function (node, boundPosition) { - var uiid = nodesCount++, - ui = nodeUIBuilder(node); - - ui.id = uiid; - ui.position = boundPosition; - ui.node = node; - - nodeProgram.createNode(ui); - - nodes[uiid] = ui; - allNodes[node.id] = ui; - return ui; - }, - - translateRel : function (dx, dy) { - transform[12] += (2 * transform[0] * dx / width) / transform[0]; - transform[13] -= (2 * transform[5] * dy / height) / transform[5]; - updateTransformUniform(); - }, - - scale : function (scaleFactor, scrollPoint) { - // Transform scroll point to clip-space coordinates: - var cx = 2 * scrollPoint.x / width - 1, - cy = 1 - (2 * scrollPoint.y) / height; - - cx -= transform[12]; - cy -= transform[13]; - - transform[12] += cx * (1 - scaleFactor); - transform[13] += cy * (1 - scaleFactor); - - transform[0] *= scaleFactor; - transform[5] *= scaleFactor; - - updateTransformUniform(); - fireRescaled(this); - - return transform[0]; - }, - - resetScale : function () { - resetScaleInternal(); - - if (gl) { - updateSize(); - // TODO: what is this? - // gl.useProgram(linksProgram); - // gl.uniform2f(linksProgram.screenSize, width, height); - updateTransformUniform(); - } - return this; - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render. - */ - init : function (c) { - var contextParameters = {}; - - if (options.preserveDrawingBuffer) { - contextParameters.preserveDrawingBuffer = true; - } - - container = c; - - updateSize(); - resetScaleInternal(); - container.appendChild(graphicsRoot); - - - gl = graphicsRoot.getContext("experimental-webgl", contextParameters); - if (!gl) { - var msg = "Could not initialize WebGL. Seems like the browser doesn't support it."; - window.alert(msg); - throw msg; - } - if (options.enableBlending) { - gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); - gl.enable(gl.BLEND); - } - if (options.clearColor) { - var color = options.clearColorValue; - gl.clearColor(color.r, color.g, color.b, color.a); - // TODO: not the best way, really. Should come up with something better - // what if we need more updates inside beginRender, like depth buffer? - this.beginRender = function () { - gl.clear(gl.COLOR_BUFFER_BIT); - }; - } - - linkProgram.load(gl); - linkProgram.updateSize(width / 2, height / 2); - - nodeProgram.load(gl); - nodeProgram.updateSize(width / 2, height / 2); - - updateTransformUniform(); - - // Notify the world if someone waited for update. TODO: should send an event - if (typeof initCallback === "function") { - initCallback(graphicsRoot); - } - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider release occupied resources. - */ - release : function (container) { - if (graphicsRoot && container) { - container.removeChild(graphicsRoot); - // TODO: anything else? - } - }, - - /** - * Checks whether webgl is supported by this browser. - */ - isSupported : function () { - var c = window.document.createElement("canvas"), - gl = c && c.getContext && c.getContext("experimental-webgl"); - return gl; - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider remove link from rendering surface. - * - * @param linkUI visual representation of the link created by link() execution. - **/ - releaseLink : function (link) { - if (linksCount > 0) { linksCount -= 1; } - var linkUI = allLinks[link.id]; - delete allLinks[link.id]; - - linkProgram.removeLink(linkUI); - - var linkIdToRemove = linkUI.id; - if (linkIdToRemove < linksCount) { - if (linksCount === 0 || linksCount === linkIdToRemove) { - return; // no more links or removed link is the last one. - } - - var lastLinkUI = links[linksCount]; - links[linkIdToRemove] = lastLinkUI; - lastLinkUI.id = linkIdToRemove; - } - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider remove node from rendering surface. - * - * @param nodeUI visual representation of the node created by node() execution. - **/ - releaseNode : function (node) { - if (nodesCount > 0) { nodesCount -= 1; } - var nodeUI = allNodes[node.id]; - delete allNodes[node.id]; - - nodeProgram.removeNode(nodeUI); - - var nodeIdToRemove = nodeUI.id; - if (nodeIdToRemove < nodesCount) { - if (nodesCount === 0 || nodesCount === nodeIdToRemove) { - return; // no more nodes or removed node is the last in the list. - } - - var lastNodeUI = nodes[nodesCount]; - - nodes[nodeIdToRemove] = lastNodeUI; - lastNodeUI.id = nodeIdToRemove; - - // Since concrete shaders may cache properties in the UI element - // we are letting them to make this swap (e.g. image node shader - // uses this approach to update node's offset in the atlas) - nodeProgram.replaceProperties(nodeUI, lastNodeUI); - } - }, - - renderNodes: function () { - var pos = {x : 0, y : 0}; - // WebGL coordinate system is different. Would be better - // to have this transform in the shader code, but it would - // require every shader to be updated.. - for (var i = 0; i < nodesCount; ++i) { - var ui = nodes[i]; - pos.x = ui.position.x; - pos.y = -ui.position.y; - if (userPlaceNodeCallback) { - userPlaceNodeCallback(ui, pos); - } - - nodeProgram.position(ui, pos); - } - }, - - renderLinks: function () { - if (this.omitLinksRendering) { return; } - - var toPos = {x : 0, y : 0}; - var fromPos = {x : 0, y : 0}; - for (var i = 0; i < linksCount; ++i) { - var ui = links[i]; - var pos = ui.pos.from; - fromPos.x = pos.x; - fromPos.y = -pos.y; - pos = ui.pos.to; - toPos.x = pos.x; - toPos.y = -pos.y; - if (userPlaceLinkCallback) { - userPlaceLinkCallback(ui, fromPos, toPos); - } - - linkProgram.position(ui, fromPos, toPos); - } - }, - - /** - * Returns root element which hosts graphics. - */ - getGraphicsRoot : function (callbackWhenReady) { - // todo: should fire an event, instead of having this context. - if (typeof callbackWhenReady === "function") { - if (graphicsRoot) { - callbackWhenReady(graphicsRoot); - } else { - initCallback = callbackWhenReady; - } - } - return graphicsRoot; - }, - - /** - * Updates default shader which renders nodes - * - * @param newProgram to use for nodes. - */ - setNodeProgram : function (newProgram) { - if (!gl && newProgram) { - // Nothing created yet. Just set shader to the new one - // and let initialization logic take care about the rest. - nodeProgram = newProgram; - } else if (newProgram) { - throw "Not implemented. Cannot swap shader on the fly... Yet."; - // TODO: unload old shader and reinit. - } - }, - - /** - * Updates default shader which renders links - * - * @param newProgram to use for links. - */ - setLinkProgram : function (newProgram) { - if (!gl && newProgram) { - // Nothing created yet. Just set shader to the new one - // and let initialization logic take care about the rest. - linkProgram = newProgram; - } else if (newProgram) { - throw "Not implemented. Cannot swap shader on the fly... Yet."; - // TODO: unload old shader and reinit. - } - }, - transformClientToGraphCoordinates : function (graphicsRootPos) { - // TODO: could be a problem when container has margins? - // to save memory we modify incoming parameter: - // point in clipspace coordinates: - graphicsRootPos.x = 2 * graphicsRootPos.x / width - 1; - graphicsRootPos.y = 1 - (2 * graphicsRootPos.y) / height; - // apply transform: - graphicsRootPos.x = (graphicsRootPos.x - transform[12]) / transform[0]; - graphicsRootPos.y = (graphicsRootPos.y - transform[13]) / transform[5]; - // now transform to graph coordinates: - graphicsRootPos.x *= width / 2; - graphicsRootPos.y *= -height / 2; - - return graphicsRootPos; - }, - - getNodeAtClientPos: function (clientPos, preciseCheck) { - if (typeof preciseCheck !== "function") { - // we don't know anything about your node structure here :( - // potentially this could be delegated to node program, but for - // right now, we are giving up if you don't pass boundary check - // callback. It answers to a question is nodeUI covers (x, y) - return null; - } - // first transform to graph coordinates: - this.transformClientToGraphCoordinates(clientPos); - // now using precise check iterate over each node and find one within box: - // TODO: This is poor O(N) performance. - for (var i = 0; i < nodesCount; ++i) { - if (preciseCheck(nodes[i], clientPos.x, clientPos.y)) { - return nodes[i].node; - } - } - return null; - } - }; - - // Let graphics fire events before we return it to the caller. - eventify(graphics); - - return graphics; -} +module.exports = renderer; + +var eventify = require('ngraph.events'); +var forceDirected = require('ngraph.forcelayout'); +var svgGraphics = require('./svgGraphics.js'); +var windowEvents = require('../Utils/windowEvents.js'); +var domInputManager = require('../Input/domInputManager.js'); +var timer = require('../Utils/timer.js'); +var getDimension = require('../Utils/getDimensions.js'); +var dragndrop = require('../Input/dragndrop.js'); + +/** + * This is heart of the rendering. Class accepts graph to be rendered and rendering settings. + * It monitors graph changes and depicts them accordingly. + * + * @param graph - Viva.Graph.graph() object to be rendered. + * @param settings - rendering settings, composed from the following parts (with their defaults shown): + * settings = { + * // Represents a module that is capable of displaying graph nodes and links. + * // all graphics has to correspond to defined interface and can be later easily + * // replaced for specific needs (e.g. adding WebGL should be piece of cake as long + * // as WebGL has implemented required interface). See svgGraphics for example. + * graphics : Viva.Graph.View.svgGraphics(), + * + * // Where the renderer should draw graph. Container size matters, because + * // renderer will attempt center graph to that size. Also graphics modules + * // might depend on it. + * container : document.body, + * + * // Defines whether graph can respond to use input + * interactive: true, + * + * // Layout algorithm to be used. The algorithm is expected to comply with defined + * // interface and is expected to be iterative. Renderer will use it then to calculate + * // grpaph's layout. For examples of the interface refer to Viva.Graph.Layout.forceDirected() + * layout : Viva.Graph.Layout.forceDirected(), + * + * // Directs renderer to display links. Usually rendering links is the slowest part of this + * // library. So if you don't need to display links, consider settings this property to false. + * renderLinks : true, + * + * // Number of layout iterations to run before displaying the graph. The bigger you set this number + * // the closer to ideal position graph will appear first time. But be careful: for large graphs + * // it can freeze the browser. + * prerender : 0 + * } + */ +function renderer(graph, settings) { + // TODO: This class is getting hard to understand. Consider refactoring. + // TODO: I have a technical debt here: fix scaling/recentering! Currently it's a total mess. + var FRAME_INTERVAL = 30; + + settings = settings || {}; + + var layout = settings.layout, + graphics = settings.graphics, + container = settings.container, + interactive = settings.interactive !== undefined ? settings.interactive : true, + inputManager, + animationTimer, + rendererInitialized = false, + updateCenterRequired = true, + + currentStep = 0, + totalIterationsCount = 0, + isStable = false, + userInteraction = false, + isPaused = false, + + viewPortOffset = { + x: 0, + y: 0 + }, + + transform = { + offsetX: 0, + offsetY: 0, + scale: 1 + }, + + publicEvents = eventify({}), + containerDrag; + + return { + /** + * Performs rendering of the graph. + * + * @param iterationsCount if specified renderer will run only given number of iterations + * and then stop. Otherwise graph rendering is performed infinitely. + * + * Note: if rendering stopped by used started dragging nodes or new nodes were added to the + * graph renderer will give run more iterations to reflect changes. + */ + run: function(iterationsCount) { + + if (!rendererInitialized) { + prepareSettings(); + prerender(); + + updateCenter(); + initDom(); + listenToEvents(); + + rendererInitialized = true; + } + + renderIterations(iterationsCount); + + return this; + }, + + reset: function() { + graphics.resetScale(); + updateCenter(); + transform.scale = 1; + }, + + pause: function() { + isPaused = true; + animationTimer.stop(); + }, + + resume: function() { + isPaused = false; + animationTimer.restart(); + }, + + rerender: function() { + renderGraph(); + return this; + }, + + zoomOut: function() { + return scale(true); + }, + + zoomIn: function() { + return scale(false); + }, + + /** + * Centers renderer at x,y graph's coordinates + */ + moveTo: function(x, y) { + graphics.graphCenterChanged(transform.offsetX - x * transform.scale, transform.offsetY - y * transform.scale); + renderGraph(); + }, + + /** + * Gets current graphics object + */ + getGraphics: function() { + return graphics; + }, + + /** + * Removes this renderer and deallocates all resources/timers + */ + dispose: function() { + stopListenToEvents(); // I quit! + }, + + on: function(eventName, callback) { + publicEvents.on(eventName, callback); + return this; + }, + + off: function(eventName, callback) { + publicEvents.off(eventName, callback); + return this; + } + }; + + /** + * Checks whether given interaction (node/scroll) is enabled + */ + function isInteractive(interactionName) { + if (typeof interactive === 'string') { + return interactive.indexOf(interactionName) >= 0; + } else if (typeof interactive === 'boolean') { + return interactive; + } + return true; // default setting + } + + function prepareSettings() { + container = container || window.document.body; + layout = layout || forceDirected(graph, forceDirected.simulator({ + springLength: 80, + springCoeff: 0.0002, + })); + graphics = graphics || svgGraphics(graph, { + container: container + }); + + if (!settings.hasOwnProperty('renderLinks')) { + settings.renderLinks = true; + } + + settings.prerender = settings.prerender || 0; + inputManager = (graphics.inputManager || domInputManager)(graph, graphics); + } + + function renderGraph() { + graphics.beginRender(); + + // todo: move this check graphics + if (settings.renderLinks) { + graphics.renderLinks(); + } + graphics.renderNodes(); + graphics.endRender(); + } + + function onRenderFrame() { + isStable = layout.step() && !userInteraction; + renderGraph(); + + return !isStable; + } + + function renderIterations(iterationsCount) { + if (animationTimer) { + totalIterationsCount += iterationsCount; + return; + } + + if (iterationsCount) { + totalIterationsCount += iterationsCount; + + animationTimer = timer(function() { + return onRenderFrame(); + }, FRAME_INTERVAL); + } else { + currentStep = 0; + totalIterationsCount = 0; + animationTimer = timer(onRenderFrame, FRAME_INTERVAL); + } + } + + function resetStable() { + if (isPaused) { + return; + } + + isStable = false; + animationTimer.restart(); + } + + function prerender() { + // To get good initial positions for the graph + // perform several prerender steps in background. + if (typeof settings.prerender === 'number' && settings.prerender > 0) { + for (var i = 0; i < settings.prerender; i += 1) { + layout.step(); + } + } + } + + function updateCenter() { + var graphRect = layout.getGraphRect(), + containerSize = getDimension(container); + + viewPortOffset.x = viewPortOffset.y = 0; + transform.offsetX = containerSize.width / 2 - (graphRect.x2 + graphRect.x1) / 2; + transform.offsetY = containerSize.height / 2 - (graphRect.y2 + graphRect.y1) / 2; + graphics.graphCenterChanged(transform.offsetX, transform.offsetY); + + updateCenterRequired = false; + } + + function createNodeUi(node) { + var nodePosition = layout.getNodePosition(node.id); + graphics.addNode(node, nodePosition); + } + + function removeNodeUi(node) { + graphics.releaseNode(node); + } + + function createLinkUi(link) { + var linkPosition = layout.getLinkPosition(link.id); + graphics.addLink(link, linkPosition); + } + + function removeLinkUi(link) { + graphics.releaseLink(link); + } + + function listenNodeEvents(node) { + if (!isInteractive('node')) { + return; + } + + var wasPinned = false; + + // TODO: This may not be memory efficient. Consider reusing handlers object. + inputManager.bindDragNDrop(node, { + onStart: function() { + wasPinned = layout.isNodePinned(node); + layout.pinNode(node, true); + userInteraction = true; + resetStable(); + }, + onDrag: function(e, offset) { + var oldPos = layout.getNodePosition(node.id); + layout.setNodePosition(node.id, + oldPos.x + offset.x / transform.scale, + oldPos.y + offset.y / transform.scale); + + userInteraction = true; + + renderGraph(); + }, + onStop: function() { + layout.pinNode(node, wasPinned); + userInteraction = false; + } + }); + } + + function releaseNodeEvents(node) { + inputManager.bindDragNDrop(node, null); + } + + function initDom() { + graphics.init(container); + + graph.forEachNode(createNodeUi); + + if (settings.renderLinks) { + graph.forEachLink(createLinkUi); + } + } + + function releaseDom() { + graphics.release(container); + } + + function processNodeChange(change) { + var node = change.node; + + if (change.changeType === 'add') { + createNodeUi(node); + listenNodeEvents(node); + if (updateCenterRequired) { + updateCenter(); + } + } else if (change.changeType === 'remove') { + releaseNodeEvents(node); + removeNodeUi(node); + if (graph.getNodesCount() === 0) { + updateCenterRequired = true; // Next time when node is added - center the graph. + } + } else if (change.changeType === 'update') { + releaseNodeEvents(node); + removeNodeUi(node); + + createNodeUi(node); + listenNodeEvents(node); + } + } + + function processLinkChange(change) { + var link = change.link; + if (change.changeType === 'add') { + if (settings.renderLinks) { + createLinkUi(link); + } + } else if (change.changeType === 'remove') { + if (settings.renderLinks) { + removeLinkUi(link); + } + } else if (change.changeType === 'update') { + throw 'Update type is not implemented. TODO: Implement me!'; + } + } + + function onGraphChanged(changes) { + var i, change; + for (i = 0; i < changes.length; i += 1) { + change = changes[i]; + if (change.node) { + processNodeChange(change); + } else if (change.link) { + processLinkChange(change); + } + } + + resetStable(); + } + + function onWindowResized() { + updateCenter(); + onRenderFrame(); + } + + function releaseContainerDragManager() { + if (containerDrag) { + containerDrag.release(); + containerDrag = null; + } + } + + function releaseGraphEvents() { + graph.off('changed', onGraphChanged); + } + + function scale(out, scrollPoint) { + if (!scrollPoint) { + var containerSize = getDimension(container); + scrollPoint = { + x: containerSize.width / 2, + y: containerSize.height / 2 + }; + } + var scaleFactor = Math.pow(1 + 0.4, out ? -0.2 : 0.2); + transform.scale = graphics.scale(scaleFactor, scrollPoint); + + renderGraph(); + publicEvents.fire('scale', transform.scale); + + return transform.scale; + } + + function listenToEvents() { + windowEvents.on('resize', onWindowResized); + + releaseContainerDragManager(); + if (isInteractive('drag')) { + containerDrag = dragndrop(container); + containerDrag.onDrag(function(e, offset) { + viewPortOffset.x += offset.x; + viewPortOffset.y += offset.y; + graphics.translateRel(offset.x, offset.y); + + renderGraph(); + }); + } + + if (isInteractive('scroll')) { + containerDrag.onScroll(function(e, scaleOffset, scrollPoint) { + scale(scaleOffset < 0, scrollPoint); + }); + } + + graph.forEachNode(listenNodeEvents); + + releaseGraphEvents(); + graph.on('changed', onGraphChanged); + } + + function stopListenToEvents() { + rendererInitialized = false; + releaseGraphEvents(); + releaseContainerDragManager(); + windowEvents.off('resize', onWindowResized); + publicEvents.off(); + animationTimer.stop(); + + graph.forEachLink(function(link) { + if (settings.renderLinks) { + removeLinkUi(link); + } + }); + + graph.forEachNode(function(node) { + releaseNodeEvents(node); + removeNodeUi(node); + }); + + layout.dispose(); + releaseDom(); + } +} + +},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.events":6,"ngraph.forcelayout":7}],50:[function(require,module,exports){ +/** + * @fileOverview Defines a graph renderer that uses SVG based drawings. + * + * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + */ + +module.exports = svgGraphics; + +var svg = require('simplesvg'); +var eventify = require('ngraph.events'); +var domInputManager = require('../Input/domInputManager.js'); + +/** + * Performs svg-based graph rendering. This module does not perform + * layout, but only visualizes nodes and edges of the graph. + */ +function svgGraphics() { + var svgContainer, + svgRoot, + offsetX, + offsetY, + initCallback, + actualScale = 1, + allNodes = {}, + allLinks = {}, +/*jshint unused: false */ + nodeBuilder = function (node) { + return svg("rect") + .attr("width", 10) + .attr("height", 10) + .attr("fill", "#00a2e8"); + }, + + nodePositionCallback = function (nodeUI, pos) { + // TODO: Remove magic 5. It should be half of the width or height of the node. + nodeUI.attr("x", pos.x - 5) + .attr("y", pos.y - 5); + }, + + linkBuilder = function (link) { + return svg("line").attr("stroke", "#999"); + }, + + linkPositionCallback = function (linkUI, fromPos, toPos) { + linkUI.attr("x1", fromPos.x) + .attr("y1", fromPos.y) + .attr("x2", toPos.x) + .attr("y2", toPos.y); + }, + + fireRescaled = function (graphics) { + // TODO: maybe we shall copy changes? + graphics.fire("rescaled"); + }, + + cachedPos = {x : 0, y: 0}, + cachedFromPos = {x : 0, y: 0}, + cachedToPos = {x : 0, y: 0}, + + updateTransform = function () { + if (svgContainer) { + var transform = "matrix(" + actualScale + ", 0, 0," + actualScale + "," + offsetX + "," + offsetY + ")"; + svgContainer.attr("transform", transform); + } + }; + + svgRoot = createSvgRoot(); + + var graphics = { + getNodeUI: function (nodeId) { + return allNodes[nodeId]; + }, + + getLinkUI: function (linkId) { + return allLinks[linkId]; + }, + + /** + * Sets the callback that creates node representation. + * + * @param builderCallback a callback function that accepts graph node + * as a parameter and must return an element representing this node. + * + * @returns If builderCallbackOrNode is a valid callback function, instance of this is returned; + * Otherwise undefined value is returned + */ + node : function (builderCallback) { + if (typeof builderCallback !== "function") { + return; // todo: throw? This is not compatible with old versions + } + + nodeBuilder = builderCallback; + + return this; + }, + + /** + * Sets the callback that creates link representation + * + * @param builderCallback a callback function that accepts graph link + * as a parameter and must return an element representing this link. + * + * @returns If builderCallback is a valid callback function, instance of this is returned; + * Otherwise undefined value is returned. + */ + link : function (builderCallback) { + if (typeof builderCallback !== "function") { + return; // todo: throw? This is not compatible with old versions + } + + linkBuilder = builderCallback; + return this; + }, + + /** + * Allows to override default position setter for the node with a new + * function. newPlaceCallback(nodeUI, position, node) is function which + * is used by updateNodePosition(). + */ + placeNode : function (newPlaceCallback) { + nodePositionCallback = newPlaceCallback; + return this; + }, + + placeLink : function (newPlaceLinkCallback) { + linkPositionCallback = newPlaceLinkCallback; + return this; + }, + + /** + * Called every before renderer starts rendering. + */ + beginRender : function () {}, + + /** + * Called every time when renderer finishes one step of rendering. + */ + endRender : function () {}, + + /** + * Sets translate operation that should be applied to all nodes and links. + */ + graphCenterChanged : function (x, y) { + offsetX = x; + offsetY = y; + updateTransform(); + }, + + /** + * Default input manager listens to DOM events to process nodes drag-n-drop + */ + inputManager : domInputManager, + + translateRel : function (dx, dy) { + var p = svgRoot.createSVGPoint(), + t = svgContainer.getCTM(), + origin = svgRoot.createSVGPoint().matrixTransform(t.inverse()); + + p.x = dx; + p.y = dy; + + p = p.matrixTransform(t.inverse()); + p.x = (p.x - origin.x) * t.a; + p.y = (p.y - origin.y) * t.d; + + t.e += p.x; + t.f += p.y; + + var transform = "matrix(" + t.a + ", 0, 0," + t.d + "," + t.e + "," + t.f + ")"; + svgContainer.attr("transform", transform); + }, + + scale : function (scaleFactor, scrollPoint) { + var p = svgRoot.createSVGPoint(); + p.x = scrollPoint.x; + p.y = scrollPoint.y; + + p = p.matrixTransform(svgContainer.getCTM().inverse()); // translate to SVG coordinates + + // Compute new scale matrix in current mouse position + var k = svgRoot.createSVGMatrix().translate(p.x, p.y).scale(scaleFactor).translate(-p.x, -p.y), + t = svgContainer.getCTM().multiply(k); + + actualScale = t.a; + offsetX = t.e; + offsetY = t.f; + var transform = "matrix(" + t.a + ", 0, 0," + t.d + "," + t.e + "," + t.f + ")"; + svgContainer.attr("transform", transform); + + fireRescaled(this); + return actualScale; + }, + + resetScale : function () { + actualScale = 1; + var transform = "matrix(1, 0, 0, 1, 0, 0)"; + svgContainer.attr("transform", transform); + fireRescaled(this); + return this; + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render. + */ + init : function (container) { + container.appendChild(svgRoot); + updateTransform(); + // Notify the world if someone waited for update. TODO: should send an event + if (typeof initCallback === "function") { + initCallback(svgRoot); + } + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider release occupied resources. + */ + release : function (container) { + if (svgRoot && container) { + container.removeChild(svgRoot); + } + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render given link of the graph + * + * @param link - model of a link + */ + addLink: function (link, pos) { + var linkUI = linkBuilder(link); + if (!linkUI) { return; } + linkUI.position = pos; + linkUI.link = link; + allLinks[link.id] = linkUI; + if (svgContainer.childElementCount > 0) { + svgContainer.insertBefore(linkUI, svgContainer.firstChild); + } else { + svgContainer.appendChild(linkUI); + } + return linkUI; + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider remove link from rendering surface. + * + * @param linkUI visual representation of the link created by link() execution. + **/ + releaseLink : function (link) { + var linkUI = allLinks[link.id]; + if (linkUI) { + svgContainer.removeChild(linkUI); + delete allLinks[link.id]; + } + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render given node of the graph. + * + * @param nodeUI visual representation of the node created by node() execution. + **/ + addNode : function (node, pos) { + var nodeUI = nodeBuilder(node); + if (!nodeUI) { + return; + } + nodeUI.position = pos; + nodeUI.node = node; + allNodes[node.id] = nodeUI; + + svgContainer.appendChild(nodeUI); + + return nodeUI; + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider remove node from rendering surface. + * + * @param node graph's node + **/ + releaseNode : function (node) { + var nodeUI = allNodes[node.id]; + if (nodeUI) { + svgContainer.removeChild(nodeUI); + delete allNodes[node.id]; + } + }, + + renderNodes : function () { + for (var key in allNodes) { + if (allNodes.hasOwnProperty(key)) { + var nodeUI = allNodes[key]; + cachedPos.x = nodeUI.position.x; + cachedPos.y = nodeUI.position.y; + nodePositionCallback(nodeUI, cachedPos, nodeUI.node); + } + } + }, + + renderLinks : function () { + for (var key in allLinks) { + if (allLinks.hasOwnProperty(key)) { + var linkUI = allLinks[key]; + cachedFromPos.x = linkUI.position.from.x; + cachedFromPos.y = linkUI.position.from.y; + cachedToPos.x = linkUI.position.to.x; + cachedToPos.y = linkUI.position.to.y; + linkPositionCallback(linkUI, cachedFromPos, cachedToPos, linkUI.link); + } + } + }, + + /** + * Returns root element which hosts graphics. + */ + getGraphicsRoot : function (callbackWhenReady) { + // todo: should fire an event, instead of having this context. + if (typeof callbackWhenReady === "function") { + if (svgRoot) { + callbackWhenReady(svgRoot); + } else { + initCallback = callbackWhenReady; + } + } + return svgRoot; + }, + /** + * Returns root SVG element. + * + * Note: This is internal method specific to this renderer + */ + getSvgRoot : function () { + return svgRoot; + } + }; + + + // Let graphics fire events before we return it to the caller. + eventify(graphics); + + return graphics; + + function createSvgRoot() { + var svgRoot = svg("svg"); + + svgContainer = svg("g") + .attr("buffered-rendering", "dynamic"); + + svgRoot.appendChild(svgContainer); + return svgRoot; + } +} + +},{"../Input/domInputManager.js":35,"ngraph.events":6,"simplesvg":28}],51:[function(require,module,exports){ +/** + * @fileOverview Defines a graph renderer that uses WebGL based drawings. + * + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka + */ + +module.exports = webglGraphics; + +var webglInputManager = require('../Input/webglInputManager.js'); +var webglLinkProgram = require('../WebGL/webglLinkProgram.js'); +var webglNodeProgram = require('../WebGL/webglNodeProgram.js'); +var webglSquare = require('../WebGL/webglSquare.js'); +var webglLine = require('../WebGL/webglLine.js'); +var eventify = require('ngraph.events'); +var merge = require('ngraph.merge'); + +/** + * Performs webgl-based graph rendering. This module does not perform + * layout, but only visualizes nodes and edges of the graph. + * + * @param options - to customize graphics behavior. Currently supported parameter + * enableBlending - true by default, allows to use transparency in node/links colors. + * preserveDrawingBuffer - false by default, tells webgl to preserve drawing buffer. + * See https://www.khronos.org/registry/webgl/specs/1.0/#5.2 + */ + +function webglGraphics(options) { + options = merge(options, { + enableBlending : true, + preserveDrawingBuffer : false, + clearColor: false, + clearColorValue : { + r : 1, + g : 1, + b : 1, + a : 1 + } + }); + + var container, + graphicsRoot, + gl, + width, + height, + nodesCount = 0, + linksCount = 0, + transform = [ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + ], + userPlaceNodeCallback, + userPlaceLinkCallback, + nodes = [], + links = [], + initCallback, + + allNodes = {}, + allLinks = {}, + linkProgram = webglLinkProgram(), + nodeProgram = webglNodeProgram(), +/*jshint unused: false */ + nodeUIBuilder = function (node) { + return webglSquare(); // Just make a square, using provided gl context (a nodeProgram); + }, + + linkUIBuilder = function (link) { + return webglLine(0xb3b3b3ff); + }, +/*jshint unused: true */ + updateTransformUniform = function () { + linkProgram.updateTransform(transform); + nodeProgram.updateTransform(transform); + }, + + resetScaleInternal = function () { + transform = [1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]; + }, + + updateSize = function () { + if (container && graphicsRoot) { + width = graphicsRoot.width = Math.max(container.offsetWidth, 1); + height = graphicsRoot.height = Math.max(container.offsetHeight, 1); + if (gl) { gl.viewport(0, 0, width, height); } + if (linkProgram) { linkProgram.updateSize(width / 2, height / 2); } + if (nodeProgram) { nodeProgram.updateSize(width / 2, height / 2); } + } + }, + + fireRescaled = function (graphics) { + graphics.fire("rescaled"); + }; + + graphicsRoot = window.document.createElement("canvas"); + + var graphics = { + getLinkUI: function (linkId) { + return allLinks[linkId]; + }, + + getNodeUI: function (nodeId) { + return allNodes[nodeId]; + }, + + /** + * Sets the callback that creates node representation. + * + * @param builderCallback a callback function that accepts graph node + * as a parameter and must return an element representing this node. + * + * @returns If builderCallbackOrNode is a valid callback function, instance of this is returned; + * Otherwise undefined value is returned + */ + node : function (builderCallback) { + if (typeof builderCallback !== "function") { + return; // todo: throw? This is not compatible with old versions + } + + nodeUIBuilder = builderCallback; + + return this; + }, + + /** + * Sets the callback that creates link representation + * + * @param builderCallback a callback function that accepts graph link + * as a parameter and must return an element representing this link. + * + * @returns If builderCallback is a valid callback function, instance of this is returned; + * Otherwise undefined value is returned. + */ + link : function (builderCallback) { + if (typeof builderCallback !== "function") { + return; // todo: throw? This is not compatible with old versions + } + + linkUIBuilder = builderCallback; + return this; + }, + + + /** + * Allows to override default position setter for the node with a new + * function. newPlaceCallback(nodeUI, position) is function which + * is used by updateNodePosition(). + */ + placeNode : function (newPlaceCallback) { + userPlaceNodeCallback = newPlaceCallback; + return this; + }, + + placeLink : function (newPlaceLinkCallback) { + userPlaceLinkCallback = newPlaceLinkCallback; + return this; + }, + + /** + * Custom input manager listens to mouse events to process nodes drag-n-drop inside WebGL canvas + */ + inputManager : webglInputManager, + + /** + * Called every time before renderer starts rendering. + */ + beginRender : function () { + // this function could be replaced by this.init, + // based on user options. + }, + + /** + * Called every time when renderer finishes one step of rendering. + */ + endRender : function () { + if (linksCount > 0) { + linkProgram.render(); + } + if (nodesCount > 0) { + nodeProgram.render(); + } + }, + + bringLinkToFront : function (linkUI) { + var frontLinkId = linkProgram.getFrontLinkId(), + srcLinkId, + temp; + + linkProgram.bringToFront(linkUI); + + if (frontLinkId > linkUI.id) { + srcLinkId = linkUI.id; + + temp = links[frontLinkId]; + links[frontLinkId] = links[srcLinkId]; + links[frontLinkId].id = frontLinkId; + links[srcLinkId] = temp; + links[srcLinkId].id = srcLinkId; + } + }, + + /** + * Sets translate operation that should be applied to all nodes and links. + */ + graphCenterChanged : function (x, y) { + transform[12] = (2 * x / width) - 1; + transform[13] = 1 - (2 * y / height); + updateTransformUniform(); + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render given link of the graph + * + * @param link - model of a link + */ + addLink: function (link, boundPosition) { + var uiid = linksCount++, + ui = linkUIBuilder(link); + ui.id = uiid; + ui.pos = boundPosition; + + linkProgram.createLink(ui); + + links[uiid] = ui; + allLinks[link.id] = ui; + return ui; + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render given node of the graph. + * + * @param nodeUI visual representation of the node created by node() execution. + **/ + addNode : function (node, boundPosition) { + var uiid = nodesCount++, + ui = nodeUIBuilder(node); + + ui.id = uiid; + ui.position = boundPosition; + ui.node = node; + + nodeProgram.createNode(ui); + + nodes[uiid] = ui; + allNodes[node.id] = ui; + return ui; + }, + + translateRel : function (dx, dy) { + transform[12] += (2 * transform[0] * dx / width) / transform[0]; + transform[13] -= (2 * transform[5] * dy / height) / transform[5]; + updateTransformUniform(); + }, + + scale : function (scaleFactor, scrollPoint) { + // Transform scroll point to clip-space coordinates: + var cx = 2 * scrollPoint.x / width - 1, + cy = 1 - (2 * scrollPoint.y) / height; + + cx -= transform[12]; + cy -= transform[13]; + + transform[12] += cx * (1 - scaleFactor); + transform[13] += cy * (1 - scaleFactor); + + transform[0] *= scaleFactor; + transform[5] *= scaleFactor; + + updateTransformUniform(); + fireRescaled(this); + + return transform[0]; + }, + + resetScale : function () { + resetScaleInternal(); + + if (gl) { + updateSize(); + // TODO: what is this? + // gl.useProgram(linksProgram); + // gl.uniform2f(linksProgram.screenSize, width, height); + updateTransformUniform(); + } + return this; + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render. + */ + init : function (c) { + var contextParameters = {}; + + if (options.preserveDrawingBuffer) { + contextParameters.preserveDrawingBuffer = true; + } + + container = c; + + updateSize(); + resetScaleInternal(); + container.appendChild(graphicsRoot); + + + gl = graphicsRoot.getContext("experimental-webgl", contextParameters); + if (!gl) { + var msg = "Could not initialize WebGL. Seems like the browser doesn't support it."; + window.alert(msg); + throw msg; + } + if (options.enableBlending) { + gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); + gl.enable(gl.BLEND); + } + if (options.clearColor) { + var color = options.clearColorValue; + gl.clearColor(color.r, color.g, color.b, color.a); + // TODO: not the best way, really. Should come up with something better + // what if we need more updates inside beginRender, like depth buffer? + this.beginRender = function () { + gl.clear(gl.COLOR_BUFFER_BIT); + }; + } + + linkProgram.load(gl); + linkProgram.updateSize(width / 2, height / 2); + + nodeProgram.load(gl); + nodeProgram.updateSize(width / 2, height / 2); + + updateTransformUniform(); + + // Notify the world if someone waited for update. TODO: should send an event + if (typeof initCallback === "function") { + initCallback(graphicsRoot); + } + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider release occupied resources. + */ + release : function (container) { + if (graphicsRoot && container) { + container.removeChild(graphicsRoot); + // TODO: anything else? + } + }, + + /** + * Checks whether webgl is supported by this browser. + */ + isSupported : function () { + var c = window.document.createElement("canvas"), + gl = c && c.getContext && c.getContext("experimental-webgl"); + return gl; + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider remove link from rendering surface. + * + * @param linkUI visual representation of the link created by link() execution. + **/ + releaseLink : function (link) { + if (linksCount > 0) { linksCount -= 1; } + var linkUI = allLinks[link.id]; + delete allLinks[link.id]; + + linkProgram.removeLink(linkUI); + + var linkIdToRemove = linkUI.id; + if (linkIdToRemove < linksCount) { + if (linksCount === 0 || linksCount === linkIdToRemove) { + return; // no more links or removed link is the last one. + } + + var lastLinkUI = links[linksCount]; + links[linkIdToRemove] = lastLinkUI; + lastLinkUI.id = linkIdToRemove; + } + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider remove node from rendering surface. + * + * @param nodeUI visual representation of the node created by node() execution. + **/ + releaseNode : function (node) { + if (nodesCount > 0) { nodesCount -= 1; } + var nodeUI = allNodes[node.id]; + delete allNodes[node.id]; + + nodeProgram.removeNode(nodeUI); + + var nodeIdToRemove = nodeUI.id; + if (nodeIdToRemove < nodesCount) { + if (nodesCount === 0 || nodesCount === nodeIdToRemove) { + return; // no more nodes or removed node is the last in the list. + } + + var lastNodeUI = nodes[nodesCount]; + + nodes[nodeIdToRemove] = lastNodeUI; + lastNodeUI.id = nodeIdToRemove; + + // Since concrete shaders may cache properties in the UI element + // we are letting them to make this swap (e.g. image node shader + // uses this approach to update node's offset in the atlas) + nodeProgram.replaceProperties(nodeUI, lastNodeUI); + } + }, + + renderNodes: function () { + var pos = {x : 0, y : 0}; + // WebGL coordinate system is different. Would be better + // to have this transform in the shader code, but it would + // require every shader to be updated.. + for (var i = 0; i < nodesCount; ++i) { + var ui = nodes[i]; + pos.x = ui.position.x; + pos.y = -ui.position.y; + if (userPlaceNodeCallback) { + userPlaceNodeCallback(ui, pos); + } + + nodeProgram.position(ui, pos); + } + }, + + renderLinks: function () { + if (this.omitLinksRendering) { return; } + + var toPos = {x : 0, y : 0}; + var fromPos = {x : 0, y : 0}; + for (var i = 0; i < linksCount; ++i) { + var ui = links[i]; + var pos = ui.pos.from; + fromPos.x = pos.x; + fromPos.y = -pos.y; + pos = ui.pos.to; + toPos.x = pos.x; + toPos.y = -pos.y; + if (userPlaceLinkCallback) { + userPlaceLinkCallback(ui, fromPos, toPos); + } + + linkProgram.position(ui, fromPos, toPos); + } + }, + + /** + * Returns root element which hosts graphics. + */ + getGraphicsRoot : function (callbackWhenReady) { + // todo: should fire an event, instead of having this context. + if (typeof callbackWhenReady === "function") { + if (graphicsRoot) { + callbackWhenReady(graphicsRoot); + } else { + initCallback = callbackWhenReady; + } + } + return graphicsRoot; + }, + + /** + * Updates default shader which renders nodes + * + * @param newProgram to use for nodes. + */ + setNodeProgram : function (newProgram) { + if (!gl && newProgram) { + // Nothing created yet. Just set shader to the new one + // and let initialization logic take care about the rest. + nodeProgram = newProgram; + } else if (newProgram) { + throw "Not implemented. Cannot swap shader on the fly... Yet."; + // TODO: unload old shader and reinit. + } + }, + + /** + * Updates default shader which renders links + * + * @param newProgram to use for links. + */ + setLinkProgram : function (newProgram) { + if (!gl && newProgram) { + // Nothing created yet. Just set shader to the new one + // and let initialization logic take care about the rest. + linkProgram = newProgram; + } else if (newProgram) { + throw "Not implemented. Cannot swap shader on the fly... Yet."; + // TODO: unload old shader and reinit. + } + }, + transformClientToGraphCoordinates : function (graphicsRootPos) { + // TODO: could be a problem when container has margins? + // to save memory we modify incoming parameter: + // point in clipspace coordinates: + graphicsRootPos.x = 2 * graphicsRootPos.x / width - 1; + graphicsRootPos.y = 1 - (2 * graphicsRootPos.y) / height; + // apply transform: + graphicsRootPos.x = (graphicsRootPos.x - transform[12]) / transform[0]; + graphicsRootPos.y = (graphicsRootPos.y - transform[13]) / transform[5]; + // now transform to graph coordinates: + graphicsRootPos.x *= width / 2; + graphicsRootPos.y *= -height / 2; + + return graphicsRootPos; + }, + + getNodeAtClientPos: function (clientPos, preciseCheck) { + if (typeof preciseCheck !== "function") { + // we don't know anything about your node structure here :( + // potentially this could be delegated to node program, but for + // right now, we are giving up if you don't pass boundary check + // callback. It answers to a question is nodeUI covers (x, y) + return null; + } + // first transform to graph coordinates: + this.transformClientToGraphCoordinates(clientPos); + // now using precise check iterate over each node and find one within box: + // TODO: This is poor O(N) performance. + for (var i = 0; i < nodesCount; ++i) { + if (preciseCheck(nodes[i], clientPos.x, clientPos.y)) { + return nodes[i].node; + } + } + return null; + } + }; + + // Let graphics fire events before we return it to the caller. + eventify(graphics); + + return graphics; +} },{"../Input/webglInputManager.js":37,"../WebGL/webglLine.js":59,"../WebGL/webglLinkProgram.js":60,"../WebGL/webglNodeProgram.js":61,"../WebGL/webglSquare.js":62,"ngraph.events":6,"ngraph.merge":25}],52:[function(require,module,exports){ module.exports = parseColor; diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 990cd36..39a1515 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-s*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=t},{}],3:[function(e,n){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n){function t(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function g(e){var n=w[e];n.mass=y(e)}function h(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function m(e){var n=w[e];return n||(c(e),n=w[e]),n}function y(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var x=e("ngraph.physics.simulator");t=t||x(),o(t,"physicsSimulator").has("step","getBestNewBodyPosition","addBodyAt");var w="function"==typeof Object.create?Object.create(null):{},b={},E=t.settings.springTransform||r;f(),u();var L={step:function(){return t.step()},getNodePosition:function(e){return m(e).pos},setNodePosition:function(e){var n=m(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return t.getBBox()},pinNode:function(e,n){var t=m(e.id);t.isPinned=!!n},isNodePinned:function(e){return m(e.id).isPinned},dispose:function(){n.off("changed",s)},getBody:a,getSpring:i,simulator:t};return L}function r(){}n.exports=t,n.exports.simulator=e("ngraph.physics.simulator");var o=e("varta")},{"ngraph.physics.simulator":8,varta:21}],8:[function(e,n){function t(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.force.reset(),v.updateBodyForce(e),m.update(e);for(n=p.length;n--;)h.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),u=n.createBounds||e("./lib/bounds"),s=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),g=u(l,n),h=f(n),m=s(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return g.update(),en))return l.splice(n,1),0===l.length&&g.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return g.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=t},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":25,"ngraph.quadtreebh":17}],9:[function(e,n){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;ut;++t){var s=e[t],f=n/s.mass;s.velocity.x+=f*s.force.x,s.velocity.y+=f*s.force.y;var c=s.velocity.x,d=s.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=t},{}],13:[function(e,n){function t(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=t},{}],14:[function(e,n){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":25,"ngraph.random":26}],15:[function(e,n){function t(e,n,t){var o="[object Array]"===Object.prototype.toString.call(t);if(o)for(var i=0;i0&&u(s.pos,a.pos));if(0===f&&u(s.pos,a.pos))return}c.push(i,s),c.push(i,a)}else{var h=a.pos.x,m=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*h,i.massY=i.massY+a.mass*m;var y=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;if(h>w){y+=1;var L=x;x=w,w+=w-L}if(m>E){y+=2;var P=b;b=E,E+=E-P}var N=t(i,y);N?c.push(N,a):(N=v(),N.left=x,N.top=b,N.right=w,N.bottom=E,N.body=a,r(i,y,N))}}},m=function(e){var n,t,r,i,a=f,u=0,c=0,l=1,p=0,v=1;for(a[0]=g;l;){var h=a[p],m=h.body;l-=1,p+=1;var y=m!==e;m&&y?(t=m.pos.x-e.pos.x,r=m.pos.y-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),n=s*m.mass*e.mass/(i*i*i),u+=n*t,c+=n*r):y&&(t=h.massX/h.mass-e.pos.x,r=h.massY/h.mass-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),(h.right-h.left)/iu&&(t=u),u>o&&(o=u),r>s&&(r=s),s>i&&(i=s)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,p=0,g=v(),g.left=t,g.right=o,g.top=r,g.bottom=i,n=a-1,n>0&&(g.body=e[n]);n--;)h(e[n],g)};return{insertBodies:y,updateBodyForce:m,options:function(e){return e?("number"==typeof e.gravity&&(s=e.gravity),"number"==typeof e.theta&&(d=e.theta),this):{gravity:s,theta:d}}}}},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":26}],18:[function(e,n){function t(){this.stack=[],this.popIdx=0}function r(e,n){this.node=e,this.body=n}n.exports=t,t.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new r(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],19:[function(e,n){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],20:[function(e,n){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],21:[function(e,n){function t(e,n){function t(){return o(e,n,arguments)}return n=n||"Argument",{has:t}}function r(){function e(e,t){return o(e,t,n)}var n=arguments;return e}function o(e,n,t){if(void 0===e)throw new Error(n+" is not defined");for(var r=0;re)throw new Error("Invalid number of nodes");var n,t=l();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function r(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=t(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function o(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=l();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function i(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=l();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function a(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=l();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function u(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=l();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function s(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=l();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var u=i*e*n,s=r+o*e+u;r>0&&a.addLink(s,r-1+o*e+u),o>0&&a.addLink(s,r+(o-1)*e+u),i>0&&a.addLink(s,r+o*e+(i-1)*e*n)}return a}function f(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=l(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function c(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=l();for(n=0;e>n;++n)t.addNode(n);return t}function d(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,u=e("ngraph.random").random(o||42),s=l();for(i=0;n>i;++i)s.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,s.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(u.nextDouble()n)return!1;B(),_.splice(n,1);var t=f(e.fromId),o=f(e.toId);return t&&(n=r(e,t.links),n>=0&&t.links.splice(n,1)),o&&(n=r(e,o.links),n>=0&&o.links.splice(n,1)),U(e,"remove"),F(),!0}function h(e,n){var t,r=f(e);if(!r)return null;for(t=0;tn;++n)e(_[n])}function x(e,n,t){var r=f(e);return r&&r.links&&"function"==typeof n?t?b(r.links,e,n):w(r.links,e,n):void 0}function w(e,n,t){for(var r,o=0;o0&&(O.fire("changed",M),M.length=0)}function N(){return Object.keys?k:A}function k(e){if("function"==typeof e)for(var n=Object.keys(j),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function o(e){this.id=e,this.links=[],this.data=null}function i(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=t;var a=e("ngraph.events")},{"ngraph.events":6}],25:[function(e,n){function t(e,n){var r;if(e||(e={}),n)for(r in n)if(n.hasOwnProperty(r)){var o=e.hasOwnProperty(r),i=typeof n[r],a=!o||typeof e[r]!==i;a?e[r]=n[r]:"object"===i&&(e[r]=t(e[r],n[r]))}return e}n.exports=t},{}],26:[function(e,n){function t(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function r(e,n){var r=n||t();if("function"!=typeof r.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var t,o,i;for(t=e.length-1;t>0;--t)o=r.next(t+1),i=e[o],e[o]=e[t],e[t]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,t,o;for(n=e.length-1;n>0;--n)t=r.next(n+1),o=e[t],e[t]=e[n],e[n]=o;return e}}}n.exports={random:t,randomIterator:r}},{}],27:[function(e,n){function t(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=t},{}],28:[function(e,n){function t(e,n){var t=r(e);if(void 0===n)return t;for(var o=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},A=function(e){p=!1,r.off("touchmove",k),r.off("touchend",A),r.off("touchcancel",A),c=null,a&&a(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,r.on("touchmove",k),r.on("touchend",A),r.on("touchcancel",A)) -},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return a=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),r.off("mousemove",w),r.off("mouseup",E),r.off("touchmove",k),r.off("touchend",A),r.off("touchcancel",A),P(null)}}}n.exports=t;var r=e("../Utils/documentEvents.js"),o=e("../Utils/browserInfo.js"),i=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":40,"../Utils/documentEvents.js":41,"../Utils/findElementPosition.js":42}],37:[function(e,n){function t(e,n){var t=r(n),o=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){o=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(o);var r=i[e.id];return r&&r.onStart&&r.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(o),o=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(o){var t=i[o.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=t;var r=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":58}],38:[function(e,n){function t(e,n){function t(e){return d[e]}n=r(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var a=o(n.seed),u=new i(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(){return{x:a.next(n.maxX),y:a.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"==typeof z?z:!0}function d(){G=G||window.document.body,F=F||o(e,o.simulator({springLength:80,springCoeff:2e-4})),O=O||i(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||u)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=s(function(){return p()},M)):(X=0,V=0,R=s(p,M)))}function g(){J||(W=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;en,t)}),e.forEachNode(E),T(),e.on("changed",j)}function D(){q=!1,T(),I(),a.off("resize",_),Q.off(),R.stop(),e.forEachLink(function(e){n.renderLinks&&b(e)}),e.forEachNode(function(e){L(e),x(e)}),F.dispose(),N()}var M=30;n=n||{};var U,R,B,F=n.layout,O=n.graphics,G=n.container,z=void 0!==n.interactive?n.interactive:!0,q=!1,Y=!0,X=0,V=0,W=!1,H=!1,J=!1,$={x:0,y:0},K={offsetX:0,offsetY:0,scale:1},Q=r({});return{run:function(e){return q||(d(),h(),m(),P(),S(),q=!0),v(e),this},reset:function(){O.resetScale(),m(),K.scale=1},pause:function(){J=!0,R.stop()},resume:function(){J=!1,R.restart()},rerender:function(){return l(),this},zoomOut:function(){return C(!0)},zoomIn:function(){return C(!1)},moveTo:function(e,n){O.graphCenterChanged(K.offsetX-e*K.scale,K.offsetY-n*K.scale),l()},getGraphics:function(){return O},dispose:function(){D()},on:function(e,n){return Q.addEventListener(e,n),this},off:function(e,n){return Q.removeEventListener(e,n),this}}}n.exports=t;var r=e("ngraph.graph"),o=e("ngraph.forcelayout"),i=e("./svgGraphics.js"),a=e("../Utils/windowEvents.js"),u=e("../Input/domInputManager.js"),s=e("../Utils/timer.js"),f=e("../Utils/getDimensions.js"),c=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.forcelayout":7,"ngraph.graph":24}],50:[function(e,n){function t(){function e(){var e=r("svg");return n=r("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,a,u,s,f=1,c={},d={},l=function(){return r("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(){return r("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+a+","+u+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){a=e,u=n,w()},inputManager:i,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),s=n.getCTM().multiply(i);f=s.a,a=s.e,u=s.f;var c="matrix("+s.a+", 0, 0,"+s.d+","+s.e+","+s.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof s&&s(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):s=e),t},getSvgRoot:function(){return t}};return o(b),b}n.exports=t;var r=e("simplesvg"),o=e("ngraph.events"),i=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":35,"ngraph.events":6,simplesvg:28}],51:[function(e,n){function t(e){e=f(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,c,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=o(),P=i(),N=function(){return a()},k=function(){return u(3014898687)},A=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),c&&c.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(k=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:r,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,A()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],A()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,A(),I(this),y[0]},resetScale:function(){return j(),c&&(_(),A()),this},init:function(r){var o={};if(e.preserveDrawingBuffer&&(o.preserveDrawingBuffer=!0),n=r,_(),j(),n.appendChild(t),c=t.getContext("experimental-webgl",o),!c){var i="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(i),i}if(e.enableBlending&&(c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA),c.enable(c.BLEND)),e.clearColor){var a=e.clearColorValue;c.clearColor(a.r,a.g,a.b,a.a),this.beginRender=function(){c.clear(c.COLOR_BUFFER_BIT)}}L.load(c),L.updateSize(d/2,l/2),P.load(c),P.updateSize(d/2,l/2),A(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!c&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!c&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return s(T),T}n.exports=t;var r=e("../Input/webglInputManager.js"),o=e("../WebGL/webglLinkProgram.js"),i=e("../WebGL/webglNodeProgram.js"),a=e("../WebGL/webglSquare.js"),u=e("../WebGL/webglLine.js"),s=e("ngraph.events"),f=e("ngraph.merge")},{"../Input/webglInputManager.js":37,"../WebGL/webglLine.js":59,"../WebGL/webglLinkProgram.js":60,"../WebGL/webglNodeProgram.js":61,"../WebGL/webglSquare.js":62,"ngraph.events":6,"ngraph.merge":25}],52:[function(e,n){function t(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=t},{}],53:[function(e,n){function t(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=t},{}],54:[function(e,n){function t(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function i(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function o(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=t},{}],55:[function(e,n){function t(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!r(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:i,getCoordinates:a,load:u};return E}function r(e){return 0===(e&e-1)}var o=e("./texture.js");n.exports=t},{"./texture.js":53}],56:[function(e,n){function t(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=t},{}],57:[function(e,n){function t(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=r(),k=o(),A=1024,j=0,_=new Float32Array(64);return{load:t,position:u,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function r(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function o(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var i=e("./webglAtlas.js"),a=e("./webgl.js");n.exports=t},{"./webgl.js":54,"./webglAtlas.js":55}],58:[function(e,n){function t(e){function n(){x=null}function t(e){x=e}function o(e){return"function"==typeof e&&k.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(k,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],k=[],A=e.getGraphicsRoot();h(A);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:o,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var r=e("../Utils/documentEvents.js");n.exports=t},{"../Utils/documentEvents.js":41}],59:[function(e,n){function t(e){return{color:r(e)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],60:[function(e,n){function t(){var e,n,t,o,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,o=r(a),e=o.createProgram(v,p),n.useProgram(e),i=o.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&o.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&o.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],61:[function(e,n){function t(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=r(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function o(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(N,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:o,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],62:[function(e,n){function t(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],63:[function(e,n){n.exports="0.7.8"},{}]},{},[1])(1)}); \ No newline at end of file +},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return a=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),r.off("mousemove",w),r.off("mouseup",E),r.off("touchmove",k),r.off("touchend",A),r.off("touchcancel",A),P(null)}}}n.exports=t;var r=e("../Utils/documentEvents.js"),o=e("../Utils/browserInfo.js"),i=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":40,"../Utils/documentEvents.js":41,"../Utils/findElementPosition.js":42}],37:[function(e,n){function t(e,n){var t=r(n),o=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){o=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(o);var r=i[e.id];return r&&r.onStart&&r.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(o),o=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(o){var t=i[o.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=t;var r=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":58}],38:[function(e,n){function t(e,n){function t(e){return d[e]}n=r(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var a=o(n.seed),u=new i(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(){return{x:a.next(n.maxX),y:a.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"==typeof z?z:!0}function d(){G=G||window.document.body,F=F||o(e,o.simulator({springLength:80,springCoeff:2e-4})),O=O||i(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||u)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=s(function(){return p()},M)):(X=0,V=0,R=s(p,M)))}function g(){J||(W=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;en,t)}),e.forEachNode(E),T(),e.on("changed",j)}function D(){q=!1,T(),I(),a.off("resize",_),Q.off(),R.stop(),e.forEachLink(function(e){n.renderLinks&&b(e)}),e.forEachNode(function(e){L(e),x(e)}),F.dispose(),N()}var M=30;n=n||{};var U,R,B,F=n.layout,O=n.graphics,G=n.container,z=void 0!==n.interactive?n.interactive:!0,q=!1,Y=!0,X=0,V=0,W=!1,H=!1,J=!1,$={x:0,y:0},K={offsetX:0,offsetY:0,scale:1},Q=r({});return{run:function(e){return q||(d(),h(),m(),P(),S(),q=!0),v(e),this},reset:function(){O.resetScale(),m(),K.scale=1},pause:function(){J=!0,R.stop()},resume:function(){J=!1,R.restart()},rerender:function(){return l(),this},zoomOut:function(){return C(!0)},zoomIn:function(){return C(!1)},moveTo:function(e,n){O.graphCenterChanged(K.offsetX-e*K.scale,K.offsetY-n*K.scale),l()},getGraphics:function(){return O},dispose:function(){D()},on:function(e,n){return Q.on(e,n),this},off:function(e,n){return Q.off(e,n),this}}}n.exports=t;var r=e("ngraph.events"),o=e("ngraph.forcelayout"),i=e("./svgGraphics.js"),a=e("../Utils/windowEvents.js"),u=e("../Input/domInputManager.js"),s=e("../Utils/timer.js"),f=e("../Utils/getDimensions.js"),c=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.events":6,"ngraph.forcelayout":7}],50:[function(e,n){function t(){function e(){var e=r("svg");return n=r("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,a,u,s,f=1,c={},d={},l=function(){return r("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(){return r("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+a+","+u+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){a=e,u=n,w()},inputManager:i,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),s=n.getCTM().multiply(i);f=s.a,a=s.e,u=s.f;var c="matrix("+s.a+", 0, 0,"+s.d+","+s.e+","+s.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof s&&s(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):s=e),t},getSvgRoot:function(){return t}};return o(b),b}n.exports=t;var r=e("simplesvg"),o=e("ngraph.events"),i=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":35,"ngraph.events":6,simplesvg:28}],51:[function(e,n){function t(e){e=f(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,c,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=o(),P=i(),N=function(){return a()},k=function(){return u(3014898687)},A=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),c&&c.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(k=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:r,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,A()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],A()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,A(),I(this),y[0]},resetScale:function(){return j(),c&&(_(),A()),this},init:function(r){var o={};if(e.preserveDrawingBuffer&&(o.preserveDrawingBuffer=!0),n=r,_(),j(),n.appendChild(t),c=t.getContext("experimental-webgl",o),!c){var i="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(i),i}if(e.enableBlending&&(c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA),c.enable(c.BLEND)),e.clearColor){var a=e.clearColorValue;c.clearColor(a.r,a.g,a.b,a.a),this.beginRender=function(){c.clear(c.COLOR_BUFFER_BIT)}}L.load(c),L.updateSize(d/2,l/2),P.load(c),P.updateSize(d/2,l/2),A(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!c&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!c&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return s(T),T}n.exports=t;var r=e("../Input/webglInputManager.js"),o=e("../WebGL/webglLinkProgram.js"),i=e("../WebGL/webglNodeProgram.js"),a=e("../WebGL/webglSquare.js"),u=e("../WebGL/webglLine.js"),s=e("ngraph.events"),f=e("ngraph.merge")},{"../Input/webglInputManager.js":37,"../WebGL/webglLine.js":59,"../WebGL/webglLinkProgram.js":60,"../WebGL/webglNodeProgram.js":61,"../WebGL/webglSquare.js":62,"ngraph.events":6,"ngraph.merge":25}],52:[function(e,n){function t(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=t},{}],53:[function(e,n){function t(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=t},{}],54:[function(e,n){function t(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function i(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function o(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=t},{}],55:[function(e,n){function t(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!r(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:i,getCoordinates:a,load:u};return E}function r(e){return 0===(e&e-1)}var o=e("./texture.js");n.exports=t},{"./texture.js":53}],56:[function(e,n){function t(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=t},{}],57:[function(e,n){function t(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=r(),k=o(),A=1024,j=0,_=new Float32Array(64);return{load:t,position:u,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function r(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function o(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var i=e("./webglAtlas.js"),a=e("./webgl.js");n.exports=t},{"./webgl.js":54,"./webglAtlas.js":55}],58:[function(e,n){function t(e){function n(){x=null}function t(e){x=e}function o(e){return"function"==typeof e&&k.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(k,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],k=[],A=e.getGraphicsRoot();h(A);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:o,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var r=e("../Utils/documentEvents.js");n.exports=t},{"../Utils/documentEvents.js":41}],59:[function(e,n){function t(e){return{color:r(e)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],60:[function(e,n){function t(){var e,n,t,o,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,o=r(a),e=o.createProgram(v,p),n.useProgram(e),i=o.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&o.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&o.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],61:[function(e,n){function t(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=r(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function o(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(N,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:o,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],62:[function(e,n){function t(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],63:[function(e,n){n.exports="0.7.8"},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/src/View/renderer.js b/src/View/renderer.js index 842dcb0..ca0e6b3 100644 --- a/src/View/renderer.js +++ b/src/View/renderer.js @@ -6,7 +6,7 @@ module.exports = renderer; -var eventify = require('ngraph.graph'); +var eventify = require('ngraph.events'); var forceDirected = require('ngraph.forcelayout'); var svgGraphics = require('./svgGraphics.js'); var windowEvents = require('../Utils/windowEvents.js'); @@ -167,12 +167,12 @@ function renderer(graph, settings) { }, on: function(eventName, callback) { - publicEvents.addEventListener(eventName, callback); + publicEvents.on(eventName, callback); return this; }, off: function(eventName, callback) { - publicEvents.removeEventListener(eventName, callback); + publicEvents.off(eventName, callback); return this; } }; From 63400ef4a4a11557ca6218dbd2cd1bc7bef5bc48 Mon Sep 17 00:00:00 2001 From: anvaka Date: Thu, 9 Apr 2015 08:22:05 -0700 Subject: [PATCH 192/276] Added test for the fix of https://github.com/anvaka/VivaGraphJS/issues/134 --- test/renderer.js | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 test/renderer.js diff --git a/test/renderer.js b/test/renderer.js new file mode 100644 index 0000000..cd96c03 --- /dev/null +++ b/test/renderer.js @@ -0,0 +1,10 @@ +var test = require('tap').test; +var Viva = require('../dist/vivagraph.js'); + +test('renderer fires scale events', function(t) { + var graph = Viva.Graph.graph(); + var renderer = Viva.Graph.View.renderer(graph); + renderer.on('scale', function noop() { }); + t.ok(true, 'event registered'); + t.end(); +}); From 09da35c276302b925e0e162db195e40b8c1fb87f Mon Sep 17 00:00:00 2001 From: anvaka Date: Thu, 9 Apr 2015 09:38:01 -0700 Subject: [PATCH 193/276] 0.7.9 --- dist/vivagraph.js | 3346 ++++++++++++++++++++--------------------- dist/vivagraph.min.js | 2 +- src/version.js | 2 +- 3 files changed, 1675 insertions(+), 1675 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index fecca6b..7fde7ba 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -1,120 +1,120 @@ !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Viva=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= 0; + } else if (typeof interactive === 'boolean') { + return interactive; + } + return true; // default setting + } + + function prepareSettings() { + container = container || window.document.body; + layout = layout || forceDirected(graph, forceDirected.simulator({ + springLength: 80, + springCoeff: 0.0002, + })); + graphics = graphics || svgGraphics(graph, { + container: container + }); + + if (!settings.hasOwnProperty('renderLinks')) { + settings.renderLinks = true; + } + + settings.prerender = settings.prerender || 0; + inputManager = (graphics.inputManager || domInputManager)(graph, graphics); + } + + function renderGraph() { + graphics.beginRender(); + + // todo: move this check graphics + if (settings.renderLinks) { + graphics.renderLinks(); + } + graphics.renderNodes(); + graphics.endRender(); + } + + function onRenderFrame() { + isStable = layout.step() && !userInteraction; + renderGraph(); + + return !isStable; + } + + function renderIterations(iterationsCount) { + if (animationTimer) { + totalIterationsCount += iterationsCount; + return; + } + + if (iterationsCount) { + totalIterationsCount += iterationsCount; + + animationTimer = timer(function() { + return onRenderFrame(); + }, FRAME_INTERVAL); + } else { + currentStep = 0; + totalIterationsCount = 0; + animationTimer = timer(onRenderFrame, FRAME_INTERVAL); + } + } + + function resetStable() { + if (isPaused) { + return; + } + + isStable = false; + animationTimer.restart(); + } + + function prerender() { + // To get good initial positions for the graph + // perform several prerender steps in background. + if (typeof settings.prerender === 'number' && settings.prerender > 0) { + for (var i = 0; i < settings.prerender; i += 1) { + layout.step(); + } + } + } + + function updateCenter() { + var graphRect = layout.getGraphRect(), + containerSize = getDimension(container); + + viewPortOffset.x = viewPortOffset.y = 0; + transform.offsetX = containerSize.width / 2 - (graphRect.x2 + graphRect.x1) / 2; + transform.offsetY = containerSize.height / 2 - (graphRect.y2 + graphRect.y1) / 2; + graphics.graphCenterChanged(transform.offsetX, transform.offsetY); + + updateCenterRequired = false; + } + + function createNodeUi(node) { + var nodePosition = layout.getNodePosition(node.id); + graphics.addNode(node, nodePosition); + } + + function removeNodeUi(node) { + graphics.releaseNode(node); + } + + function createLinkUi(link) { + var linkPosition = layout.getLinkPosition(link.id); + graphics.addLink(link, linkPosition); + } + + function removeLinkUi(link) { + graphics.releaseLink(link); + } + + function listenNodeEvents(node) { + if (!isInteractive('node')) { + return; + } + + var wasPinned = false; + + // TODO: This may not be memory efficient. Consider reusing handlers object. + inputManager.bindDragNDrop(node, { + onStart: function() { + wasPinned = layout.isNodePinned(node); + layout.pinNode(node, true); + userInteraction = true; + resetStable(); + }, + onDrag: function(e, offset) { + var oldPos = layout.getNodePosition(node.id); + layout.setNodePosition(node.id, + oldPos.x + offset.x / transform.scale, + oldPos.y + offset.y / transform.scale); + + userInteraction = true; + + renderGraph(); + }, + onStop: function() { + layout.pinNode(node, wasPinned); + userInteraction = false; + } + }); + } + + function releaseNodeEvents(node) { + inputManager.bindDragNDrop(node, null); + } + + function initDom() { + graphics.init(container); + + graph.forEachNode(createNodeUi); + + if (settings.renderLinks) { + graph.forEachLink(createLinkUi); + } + } + + function releaseDom() { + graphics.release(container); + } + + function processNodeChange(change) { + var node = change.node; + + if (change.changeType === 'add') { + createNodeUi(node); + listenNodeEvents(node); + if (updateCenterRequired) { + updateCenter(); + } + } else if (change.changeType === 'remove') { + releaseNodeEvents(node); + removeNodeUi(node); + if (graph.getNodesCount() === 0) { + updateCenterRequired = true; // Next time when node is added - center the graph. + } + } else if (change.changeType === 'update') { + releaseNodeEvents(node); + removeNodeUi(node); + + createNodeUi(node); + listenNodeEvents(node); + } + } + + function processLinkChange(change) { + var link = change.link; + if (change.changeType === 'add') { + if (settings.renderLinks) { + createLinkUi(link); + } + } else if (change.changeType === 'remove') { + if (settings.renderLinks) { + removeLinkUi(link); + } + } else if (change.changeType === 'update') { + throw 'Update type is not implemented. TODO: Implement me!'; + } + } + + function onGraphChanged(changes) { + var i, change; + for (i = 0; i < changes.length; i += 1) { + change = changes[i]; + if (change.node) { + processNodeChange(change); + } else if (change.link) { + processLinkChange(change); + } + } + + resetStable(); + } + + function onWindowResized() { + updateCenter(); + onRenderFrame(); + } + + function releaseContainerDragManager() { + if (containerDrag) { + containerDrag.release(); + containerDrag = null; + } + } + + function releaseGraphEvents() { + graph.off('changed', onGraphChanged); + } + + function scale(out, scrollPoint) { + if (!scrollPoint) { + var containerSize = getDimension(container); + scrollPoint = { + x: containerSize.width / 2, + y: containerSize.height / 2 + }; + } + var scaleFactor = Math.pow(1 + 0.4, out ? -0.2 : 0.2); + transform.scale = graphics.scale(scaleFactor, scrollPoint); + + renderGraph(); + publicEvents.fire('scale', transform.scale); + + return transform.scale; + } + + function listenToEvents() { + windowEvents.on('resize', onWindowResized); + + releaseContainerDragManager(); + if (isInteractive('drag')) { + containerDrag = dragndrop(container); + containerDrag.onDrag(function(e, offset) { + viewPortOffset.x += offset.x; + viewPortOffset.y += offset.y; + graphics.translateRel(offset.x, offset.y); + + renderGraph(); + }); + } + + if (isInteractive('scroll')) { + containerDrag.onScroll(function(e, scaleOffset, scrollPoint) { + scale(scaleOffset < 0, scrollPoint); + }); + } + + graph.forEachNode(listenNodeEvents); + + releaseGraphEvents(); + graph.on('changed', onGraphChanged); + } + + function stopListenToEvents() { + rendererInitialized = false; + releaseGraphEvents(); + releaseContainerDragManager(); + windowEvents.off('resize', onWindowResized); + publicEvents.off(); + animationTimer.stop(); + + graph.forEachLink(function(link) { + if (settings.renderLinks) { + removeLinkUi(link); + } + }); + + graph.forEachNode(function(node) { + releaseNodeEvents(node); + removeNodeUi(node); + }); + + layout.dispose(); + releaseDom(); + } +} - updateCenter(); - initDom(); - listenToEvents(); - - rendererInitialized = true; - } - - renderIterations(iterationsCount); - - return this; - }, - - reset: function() { - graphics.resetScale(); - updateCenter(); - transform.scale = 1; - }, - - pause: function() { - isPaused = true; - animationTimer.stop(); - }, - - resume: function() { - isPaused = false; - animationTimer.restart(); - }, - - rerender: function() { - renderGraph(); - return this; - }, - - zoomOut: function() { - return scale(true); - }, - - zoomIn: function() { - return scale(false); - }, - - /** - * Centers renderer at x,y graph's coordinates - */ - moveTo: function(x, y) { - graphics.graphCenterChanged(transform.offsetX - x * transform.scale, transform.offsetY - y * transform.scale); - renderGraph(); - }, - - /** - * Gets current graphics object - */ - getGraphics: function() { - return graphics; - }, - - /** - * Removes this renderer and deallocates all resources/timers - */ - dispose: function() { - stopListenToEvents(); // I quit! - }, - - on: function(eventName, callback) { - publicEvents.on(eventName, callback); - return this; - }, - - off: function(eventName, callback) { - publicEvents.off(eventName, callback); - return this; - } - }; - - /** - * Checks whether given interaction (node/scroll) is enabled - */ - function isInteractive(interactionName) { - if (typeof interactive === 'string') { - return interactive.indexOf(interactionName) >= 0; - } else if (typeof interactive === 'boolean') { - return interactive; - } - return true; // default setting - } - - function prepareSettings() { - container = container || window.document.body; - layout = layout || forceDirected(graph, forceDirected.simulator({ - springLength: 80, - springCoeff: 0.0002, - })); - graphics = graphics || svgGraphics(graph, { - container: container - }); - - if (!settings.hasOwnProperty('renderLinks')) { - settings.renderLinks = true; - } - - settings.prerender = settings.prerender || 0; - inputManager = (graphics.inputManager || domInputManager)(graph, graphics); - } - - function renderGraph() { - graphics.beginRender(); - - // todo: move this check graphics - if (settings.renderLinks) { - graphics.renderLinks(); - } - graphics.renderNodes(); - graphics.endRender(); - } - - function onRenderFrame() { - isStable = layout.step() && !userInteraction; - renderGraph(); - - return !isStable; - } - - function renderIterations(iterationsCount) { - if (animationTimer) { - totalIterationsCount += iterationsCount; - return; - } - - if (iterationsCount) { - totalIterationsCount += iterationsCount; - - animationTimer = timer(function() { - return onRenderFrame(); - }, FRAME_INTERVAL); - } else { - currentStep = 0; - totalIterationsCount = 0; - animationTimer = timer(onRenderFrame, FRAME_INTERVAL); - } - } - - function resetStable() { - if (isPaused) { - return; - } - - isStable = false; - animationTimer.restart(); - } - - function prerender() { - // To get good initial positions for the graph - // perform several prerender steps in background. - if (typeof settings.prerender === 'number' && settings.prerender > 0) { - for (var i = 0; i < settings.prerender; i += 1) { - layout.step(); - } - } - } - - function updateCenter() { - var graphRect = layout.getGraphRect(), - containerSize = getDimension(container); - - viewPortOffset.x = viewPortOffset.y = 0; - transform.offsetX = containerSize.width / 2 - (graphRect.x2 + graphRect.x1) / 2; - transform.offsetY = containerSize.height / 2 - (graphRect.y2 + graphRect.y1) / 2; - graphics.graphCenterChanged(transform.offsetX, transform.offsetY); - - updateCenterRequired = false; - } - - function createNodeUi(node) { - var nodePosition = layout.getNodePosition(node.id); - graphics.addNode(node, nodePosition); - } - - function removeNodeUi(node) { - graphics.releaseNode(node); - } - - function createLinkUi(link) { - var linkPosition = layout.getLinkPosition(link.id); - graphics.addLink(link, linkPosition); - } - - function removeLinkUi(link) { - graphics.releaseLink(link); - } - - function listenNodeEvents(node) { - if (!isInteractive('node')) { - return; - } - - var wasPinned = false; - - // TODO: This may not be memory efficient. Consider reusing handlers object. - inputManager.bindDragNDrop(node, { - onStart: function() { - wasPinned = layout.isNodePinned(node); - layout.pinNode(node, true); - userInteraction = true; - resetStable(); - }, - onDrag: function(e, offset) { - var oldPos = layout.getNodePosition(node.id); - layout.setNodePosition(node.id, - oldPos.x + offset.x / transform.scale, - oldPos.y + offset.y / transform.scale); - - userInteraction = true; - - renderGraph(); - }, - onStop: function() { - layout.pinNode(node, wasPinned); - userInteraction = false; - } - }); - } - - function releaseNodeEvents(node) { - inputManager.bindDragNDrop(node, null); - } - - function initDom() { - graphics.init(container); - - graph.forEachNode(createNodeUi); - - if (settings.renderLinks) { - graph.forEachLink(createLinkUi); - } - } - - function releaseDom() { - graphics.release(container); - } - - function processNodeChange(change) { - var node = change.node; - - if (change.changeType === 'add') { - createNodeUi(node); - listenNodeEvents(node); - if (updateCenterRequired) { - updateCenter(); - } - } else if (change.changeType === 'remove') { - releaseNodeEvents(node); - removeNodeUi(node); - if (graph.getNodesCount() === 0) { - updateCenterRequired = true; // Next time when node is added - center the graph. - } - } else if (change.changeType === 'update') { - releaseNodeEvents(node); - removeNodeUi(node); - - createNodeUi(node); - listenNodeEvents(node); - } - } - - function processLinkChange(change) { - var link = change.link; - if (change.changeType === 'add') { - if (settings.renderLinks) { - createLinkUi(link); - } - } else if (change.changeType === 'remove') { - if (settings.renderLinks) { - removeLinkUi(link); - } - } else if (change.changeType === 'update') { - throw 'Update type is not implemented. TODO: Implement me!'; - } - } - - function onGraphChanged(changes) { - var i, change; - for (i = 0; i < changes.length; i += 1) { - change = changes[i]; - if (change.node) { - processNodeChange(change); - } else if (change.link) { - processLinkChange(change); - } - } - - resetStable(); - } - - function onWindowResized() { - updateCenter(); - onRenderFrame(); - } - - function releaseContainerDragManager() { - if (containerDrag) { - containerDrag.release(); - containerDrag = null; - } - } - - function releaseGraphEvents() { - graph.off('changed', onGraphChanged); - } - - function scale(out, scrollPoint) { - if (!scrollPoint) { - var containerSize = getDimension(container); - scrollPoint = { - x: containerSize.width / 2, - y: containerSize.height / 2 - }; - } - var scaleFactor = Math.pow(1 + 0.4, out ? -0.2 : 0.2); - transform.scale = graphics.scale(scaleFactor, scrollPoint); - - renderGraph(); - publicEvents.fire('scale', transform.scale); - - return transform.scale; - } - - function listenToEvents() { - windowEvents.on('resize', onWindowResized); - - releaseContainerDragManager(); - if (isInteractive('drag')) { - containerDrag = dragndrop(container); - containerDrag.onDrag(function(e, offset) { - viewPortOffset.x += offset.x; - viewPortOffset.y += offset.y; - graphics.translateRel(offset.x, offset.y); - - renderGraph(); - }); - } - - if (isInteractive('scroll')) { - containerDrag.onScroll(function(e, scaleOffset, scrollPoint) { - scale(scaleOffset < 0, scrollPoint); - }); - } - - graph.forEachNode(listenNodeEvents); - - releaseGraphEvents(); - graph.on('changed', onGraphChanged); - } - - function stopListenToEvents() { - rendererInitialized = false; - releaseGraphEvents(); - releaseContainerDragManager(); - windowEvents.off('resize', onWindowResized); - publicEvents.off(); - animationTimer.stop(); - - graph.forEachLink(function(link) { - if (settings.renderLinks) { - removeLinkUi(link); - } - }); - - graph.forEachNode(function(node) { - releaseNodeEvents(node); - removeNodeUi(node); - }); - - layout.dispose(); - releaseDom(); - } -} - -},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.events":6,"ngraph.forcelayout":7}],50:[function(require,module,exports){ -/** - * @fileOverview Defines a graph renderer that uses SVG based drawings. - * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com - */ - -module.exports = svgGraphics; - -var svg = require('simplesvg'); -var eventify = require('ngraph.events'); -var domInputManager = require('../Input/domInputManager.js'); - -/** - * Performs svg-based graph rendering. This module does not perform - * layout, but only visualizes nodes and edges of the graph. - */ -function svgGraphics() { - var svgContainer, - svgRoot, - offsetX, - offsetY, - initCallback, - actualScale = 1, - allNodes = {}, - allLinks = {}, -/*jshint unused: false */ - nodeBuilder = function (node) { - return svg("rect") - .attr("width", 10) - .attr("height", 10) - .attr("fill", "#00a2e8"); - }, - - nodePositionCallback = function (nodeUI, pos) { - // TODO: Remove magic 5. It should be half of the width or height of the node. - nodeUI.attr("x", pos.x - 5) - .attr("y", pos.y - 5); - }, - - linkBuilder = function (link) { - return svg("line").attr("stroke", "#999"); - }, - - linkPositionCallback = function (linkUI, fromPos, toPos) { - linkUI.attr("x1", fromPos.x) - .attr("y1", fromPos.y) - .attr("x2", toPos.x) - .attr("y2", toPos.y); - }, - - fireRescaled = function (graphics) { - // TODO: maybe we shall copy changes? - graphics.fire("rescaled"); - }, - - cachedPos = {x : 0, y: 0}, - cachedFromPos = {x : 0, y: 0}, - cachedToPos = {x : 0, y: 0}, - - updateTransform = function () { - if (svgContainer) { - var transform = "matrix(" + actualScale + ", 0, 0," + actualScale + "," + offsetX + "," + offsetY + ")"; - svgContainer.attr("transform", transform); - } - }; - - svgRoot = createSvgRoot(); - - var graphics = { - getNodeUI: function (nodeId) { - return allNodes[nodeId]; - }, - - getLinkUI: function (linkId) { - return allLinks[linkId]; - }, - - /** - * Sets the callback that creates node representation. - * - * @param builderCallback a callback function that accepts graph node - * as a parameter and must return an element representing this node. - * - * @returns If builderCallbackOrNode is a valid callback function, instance of this is returned; - * Otherwise undefined value is returned - */ - node : function (builderCallback) { - if (typeof builderCallback !== "function") { - return; // todo: throw? This is not compatible with old versions - } - - nodeBuilder = builderCallback; - - return this; - }, - - /** - * Sets the callback that creates link representation - * - * @param builderCallback a callback function that accepts graph link - * as a parameter and must return an element representing this link. - * - * @returns If builderCallback is a valid callback function, instance of this is returned; - * Otherwise undefined value is returned. - */ - link : function (builderCallback) { - if (typeof builderCallback !== "function") { - return; // todo: throw? This is not compatible with old versions - } - - linkBuilder = builderCallback; - return this; - }, - - /** - * Allows to override default position setter for the node with a new - * function. newPlaceCallback(nodeUI, position, node) is function which - * is used by updateNodePosition(). - */ - placeNode : function (newPlaceCallback) { - nodePositionCallback = newPlaceCallback; - return this; - }, - - placeLink : function (newPlaceLinkCallback) { - linkPositionCallback = newPlaceLinkCallback; - return this; - }, - - /** - * Called every before renderer starts rendering. - */ - beginRender : function () {}, - - /** - * Called every time when renderer finishes one step of rendering. - */ - endRender : function () {}, - - /** - * Sets translate operation that should be applied to all nodes and links. - */ - graphCenterChanged : function (x, y) { - offsetX = x; - offsetY = y; - updateTransform(); - }, - - /** - * Default input manager listens to DOM events to process nodes drag-n-drop - */ - inputManager : domInputManager, - - translateRel : function (dx, dy) { - var p = svgRoot.createSVGPoint(), - t = svgContainer.getCTM(), - origin = svgRoot.createSVGPoint().matrixTransform(t.inverse()); - - p.x = dx; - p.y = dy; - - p = p.matrixTransform(t.inverse()); - p.x = (p.x - origin.x) * t.a; - p.y = (p.y - origin.y) * t.d; - - t.e += p.x; - t.f += p.y; - - var transform = "matrix(" + t.a + ", 0, 0," + t.d + "," + t.e + "," + t.f + ")"; - svgContainer.attr("transform", transform); - }, - - scale : function (scaleFactor, scrollPoint) { - var p = svgRoot.createSVGPoint(); - p.x = scrollPoint.x; - p.y = scrollPoint.y; - - p = p.matrixTransform(svgContainer.getCTM().inverse()); // translate to SVG coordinates - - // Compute new scale matrix in current mouse position - var k = svgRoot.createSVGMatrix().translate(p.x, p.y).scale(scaleFactor).translate(-p.x, -p.y), - t = svgContainer.getCTM().multiply(k); - - actualScale = t.a; - offsetX = t.e; - offsetY = t.f; - var transform = "matrix(" + t.a + ", 0, 0," + t.d + "," + t.e + "," + t.f + ")"; - svgContainer.attr("transform", transform); - - fireRescaled(this); - return actualScale; - }, - - resetScale : function () { - actualScale = 1; - var transform = "matrix(1, 0, 0, 1, 0, 0)"; - svgContainer.attr("transform", transform); - fireRescaled(this); - return this; - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render. - */ - init : function (container) { - container.appendChild(svgRoot); - updateTransform(); - // Notify the world if someone waited for update. TODO: should send an event - if (typeof initCallback === "function") { - initCallback(svgRoot); - } - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider release occupied resources. - */ - release : function (container) { - if (svgRoot && container) { - container.removeChild(svgRoot); - } - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render given link of the graph - * - * @param link - model of a link - */ - addLink: function (link, pos) { - var linkUI = linkBuilder(link); - if (!linkUI) { return; } - linkUI.position = pos; - linkUI.link = link; - allLinks[link.id] = linkUI; - if (svgContainer.childElementCount > 0) { - svgContainer.insertBefore(linkUI, svgContainer.firstChild); - } else { - svgContainer.appendChild(linkUI); - } - return linkUI; - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider remove link from rendering surface. - * - * @param linkUI visual representation of the link created by link() execution. - **/ - releaseLink : function (link) { - var linkUI = allLinks[link.id]; - if (linkUI) { - svgContainer.removeChild(linkUI); - delete allLinks[link.id]; - } - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render given node of the graph. - * - * @param nodeUI visual representation of the node created by node() execution. - **/ - addNode : function (node, pos) { - var nodeUI = nodeBuilder(node); - if (!nodeUI) { - return; - } - nodeUI.position = pos; - nodeUI.node = node; - allNodes[node.id] = nodeUI; - - svgContainer.appendChild(nodeUI); - - return nodeUI; - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider remove node from rendering surface. - * - * @param node graph's node - **/ - releaseNode : function (node) { - var nodeUI = allNodes[node.id]; - if (nodeUI) { - svgContainer.removeChild(nodeUI); - delete allNodes[node.id]; - } - }, - - renderNodes : function () { - for (var key in allNodes) { - if (allNodes.hasOwnProperty(key)) { - var nodeUI = allNodes[key]; - cachedPos.x = nodeUI.position.x; - cachedPos.y = nodeUI.position.y; - nodePositionCallback(nodeUI, cachedPos, nodeUI.node); - } - } - }, - - renderLinks : function () { - for (var key in allLinks) { - if (allLinks.hasOwnProperty(key)) { - var linkUI = allLinks[key]; - cachedFromPos.x = linkUI.position.from.x; - cachedFromPos.y = linkUI.position.from.y; - cachedToPos.x = linkUI.position.to.x; - cachedToPos.y = linkUI.position.to.y; - linkPositionCallback(linkUI, cachedFromPos, cachedToPos, linkUI.link); - } - } - }, - - /** - * Returns root element which hosts graphics. - */ - getGraphicsRoot : function (callbackWhenReady) { - // todo: should fire an event, instead of having this context. - if (typeof callbackWhenReady === "function") { - if (svgRoot) { - callbackWhenReady(svgRoot); - } else { - initCallback = callbackWhenReady; - } - } - return svgRoot; - }, - /** - * Returns root SVG element. - * - * Note: This is internal method specific to this renderer - */ - getSvgRoot : function () { - return svgRoot; - } - }; - - - // Let graphics fire events before we return it to the caller. - eventify(graphics); - - return graphics; - - function createSvgRoot() { - var svgRoot = svg("svg"); - - svgContainer = svg("g") - .attr("buffered-rendering", "dynamic"); - - svgRoot.appendChild(svgContainer); - return svgRoot; - } -} +},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.events":6,"ngraph.forcelayout":7}],50:[function(require,module,exports){ +/** + * @fileOverview Defines a graph renderer that uses SVG based drawings. + * + * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + */ + +module.exports = svgGraphics; + +var svg = require('simplesvg'); +var eventify = require('ngraph.events'); +var domInputManager = require('../Input/domInputManager.js'); + +/** + * Performs svg-based graph rendering. This module does not perform + * layout, but only visualizes nodes and edges of the graph. + */ +function svgGraphics() { + var svgContainer, + svgRoot, + offsetX, + offsetY, + initCallback, + actualScale = 1, + allNodes = {}, + allLinks = {}, +/*jshint unused: false */ + nodeBuilder = function (node) { + return svg("rect") + .attr("width", 10) + .attr("height", 10) + .attr("fill", "#00a2e8"); + }, + + nodePositionCallback = function (nodeUI, pos) { + // TODO: Remove magic 5. It should be half of the width or height of the node. + nodeUI.attr("x", pos.x - 5) + .attr("y", pos.y - 5); + }, + + linkBuilder = function (link) { + return svg("line").attr("stroke", "#999"); + }, + + linkPositionCallback = function (linkUI, fromPos, toPos) { + linkUI.attr("x1", fromPos.x) + .attr("y1", fromPos.y) + .attr("x2", toPos.x) + .attr("y2", toPos.y); + }, + + fireRescaled = function (graphics) { + // TODO: maybe we shall copy changes? + graphics.fire("rescaled"); + }, + + cachedPos = {x : 0, y: 0}, + cachedFromPos = {x : 0, y: 0}, + cachedToPos = {x : 0, y: 0}, + + updateTransform = function () { + if (svgContainer) { + var transform = "matrix(" + actualScale + ", 0, 0," + actualScale + "," + offsetX + "," + offsetY + ")"; + svgContainer.attr("transform", transform); + } + }; + + svgRoot = createSvgRoot(); + + var graphics = { + getNodeUI: function (nodeId) { + return allNodes[nodeId]; + }, + + getLinkUI: function (linkId) { + return allLinks[linkId]; + }, + + /** + * Sets the callback that creates node representation. + * + * @param builderCallback a callback function that accepts graph node + * as a parameter and must return an element representing this node. + * + * @returns If builderCallbackOrNode is a valid callback function, instance of this is returned; + * Otherwise undefined value is returned + */ + node : function (builderCallback) { + if (typeof builderCallback !== "function") { + return; // todo: throw? This is not compatible with old versions + } + + nodeBuilder = builderCallback; + + return this; + }, + + /** + * Sets the callback that creates link representation + * + * @param builderCallback a callback function that accepts graph link + * as a parameter and must return an element representing this link. + * + * @returns If builderCallback is a valid callback function, instance of this is returned; + * Otherwise undefined value is returned. + */ + link : function (builderCallback) { + if (typeof builderCallback !== "function") { + return; // todo: throw? This is not compatible with old versions + } + + linkBuilder = builderCallback; + return this; + }, + + /** + * Allows to override default position setter for the node with a new + * function. newPlaceCallback(nodeUI, position, node) is function which + * is used by updateNodePosition(). + */ + placeNode : function (newPlaceCallback) { + nodePositionCallback = newPlaceCallback; + return this; + }, + + placeLink : function (newPlaceLinkCallback) { + linkPositionCallback = newPlaceLinkCallback; + return this; + }, + + /** + * Called every before renderer starts rendering. + */ + beginRender : function () {}, + + /** + * Called every time when renderer finishes one step of rendering. + */ + endRender : function () {}, + + /** + * Sets translate operation that should be applied to all nodes and links. + */ + graphCenterChanged : function (x, y) { + offsetX = x; + offsetY = y; + updateTransform(); + }, + + /** + * Default input manager listens to DOM events to process nodes drag-n-drop + */ + inputManager : domInputManager, + + translateRel : function (dx, dy) { + var p = svgRoot.createSVGPoint(), + t = svgContainer.getCTM(), + origin = svgRoot.createSVGPoint().matrixTransform(t.inverse()); + + p.x = dx; + p.y = dy; + + p = p.matrixTransform(t.inverse()); + p.x = (p.x - origin.x) * t.a; + p.y = (p.y - origin.y) * t.d; + + t.e += p.x; + t.f += p.y; + + var transform = "matrix(" + t.a + ", 0, 0," + t.d + "," + t.e + "," + t.f + ")"; + svgContainer.attr("transform", transform); + }, + + scale : function (scaleFactor, scrollPoint) { + var p = svgRoot.createSVGPoint(); + p.x = scrollPoint.x; + p.y = scrollPoint.y; + + p = p.matrixTransform(svgContainer.getCTM().inverse()); // translate to SVG coordinates + + // Compute new scale matrix in current mouse position + var k = svgRoot.createSVGMatrix().translate(p.x, p.y).scale(scaleFactor).translate(-p.x, -p.y), + t = svgContainer.getCTM().multiply(k); + + actualScale = t.a; + offsetX = t.e; + offsetY = t.f; + var transform = "matrix(" + t.a + ", 0, 0," + t.d + "," + t.e + "," + t.f + ")"; + svgContainer.attr("transform", transform); + + fireRescaled(this); + return actualScale; + }, + + resetScale : function () { + actualScale = 1; + var transform = "matrix(1, 0, 0, 1, 0, 0)"; + svgContainer.attr("transform", transform); + fireRescaled(this); + return this; + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render. + */ + init : function (container) { + container.appendChild(svgRoot); + updateTransform(); + // Notify the world if someone waited for update. TODO: should send an event + if (typeof initCallback === "function") { + initCallback(svgRoot); + } + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider release occupied resources. + */ + release : function (container) { + if (svgRoot && container) { + container.removeChild(svgRoot); + } + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render given link of the graph + * + * @param link - model of a link + */ + addLink: function (link, pos) { + var linkUI = linkBuilder(link); + if (!linkUI) { return; } + linkUI.position = pos; + linkUI.link = link; + allLinks[link.id] = linkUI; + if (svgContainer.childElementCount > 0) { + svgContainer.insertBefore(linkUI, svgContainer.firstChild); + } else { + svgContainer.appendChild(linkUI); + } + return linkUI; + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider remove link from rendering surface. + * + * @param linkUI visual representation of the link created by link() execution. + **/ + releaseLink : function (link) { + var linkUI = allLinks[link.id]; + if (linkUI) { + svgContainer.removeChild(linkUI); + delete allLinks[link.id]; + } + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render given node of the graph. + * + * @param nodeUI visual representation of the node created by node() execution. + **/ + addNode : function (node, pos) { + var nodeUI = nodeBuilder(node); + if (!nodeUI) { + return; + } + nodeUI.position = pos; + nodeUI.node = node; + allNodes[node.id] = nodeUI; + + svgContainer.appendChild(nodeUI); + + return nodeUI; + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider remove node from rendering surface. + * + * @param node graph's node + **/ + releaseNode : function (node) { + var nodeUI = allNodes[node.id]; + if (nodeUI) { + svgContainer.removeChild(nodeUI); + delete allNodes[node.id]; + } + }, + + renderNodes : function () { + for (var key in allNodes) { + if (allNodes.hasOwnProperty(key)) { + var nodeUI = allNodes[key]; + cachedPos.x = nodeUI.position.x; + cachedPos.y = nodeUI.position.y; + nodePositionCallback(nodeUI, cachedPos, nodeUI.node); + } + } + }, + + renderLinks : function () { + for (var key in allLinks) { + if (allLinks.hasOwnProperty(key)) { + var linkUI = allLinks[key]; + cachedFromPos.x = linkUI.position.from.x; + cachedFromPos.y = linkUI.position.from.y; + cachedToPos.x = linkUI.position.to.x; + cachedToPos.y = linkUI.position.to.y; + linkPositionCallback(linkUI, cachedFromPos, cachedToPos, linkUI.link); + } + } + }, + + /** + * Returns root element which hosts graphics. + */ + getGraphicsRoot : function (callbackWhenReady) { + // todo: should fire an event, instead of having this context. + if (typeof callbackWhenReady === "function") { + if (svgRoot) { + callbackWhenReady(svgRoot); + } else { + initCallback = callbackWhenReady; + } + } + return svgRoot; + }, + /** + * Returns root SVG element. + * + * Note: This is internal method specific to this renderer + */ + getSvgRoot : function () { + return svgRoot; + } + }; + + + // Let graphics fire events before we return it to the caller. + eventify(graphics); + + return graphics; + + function createSvgRoot() { + var svgRoot = svg("svg"); + + svgContainer = svg("g") + .attr("buffered-rendering", "dynamic"); + + svgRoot.appendChild(svgContainer); + return svgRoot; + } +} },{"../Input/domInputManager.js":35,"ngraph.events":6,"simplesvg":28}],51:[function(require,module,exports){ -/** - * @fileOverview Defines a graph renderer that uses WebGL based drawings. - * - * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka - */ - -module.exports = webglGraphics; - -var webglInputManager = require('../Input/webglInputManager.js'); -var webglLinkProgram = require('../WebGL/webglLinkProgram.js'); -var webglNodeProgram = require('../WebGL/webglNodeProgram.js'); -var webglSquare = require('../WebGL/webglSquare.js'); -var webglLine = require('../WebGL/webglLine.js'); -var eventify = require('ngraph.events'); -var merge = require('ngraph.merge'); - -/** - * Performs webgl-based graph rendering. This module does not perform - * layout, but only visualizes nodes and edges of the graph. - * - * @param options - to customize graphics behavior. Currently supported parameter - * enableBlending - true by default, allows to use transparency in node/links colors. - * preserveDrawingBuffer - false by default, tells webgl to preserve drawing buffer. - * See https://www.khronos.org/registry/webgl/specs/1.0/#5.2 - */ - -function webglGraphics(options) { - options = merge(options, { - enableBlending : true, - preserveDrawingBuffer : false, - clearColor: false, - clearColorValue : { - r : 1, - g : 1, - b : 1, - a : 1 - } - }); - - var container, - graphicsRoot, - gl, - width, - height, - nodesCount = 0, - linksCount = 0, - transform = [ - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - ], - userPlaceNodeCallback, - userPlaceLinkCallback, - nodes = [], - links = [], - initCallback, - - allNodes = {}, - allLinks = {}, - linkProgram = webglLinkProgram(), - nodeProgram = webglNodeProgram(), -/*jshint unused: false */ - nodeUIBuilder = function (node) { - return webglSquare(); // Just make a square, using provided gl context (a nodeProgram); - }, - - linkUIBuilder = function (link) { - return webglLine(0xb3b3b3ff); - }, -/*jshint unused: true */ - updateTransformUniform = function () { - linkProgram.updateTransform(transform); - nodeProgram.updateTransform(transform); - }, - - resetScaleInternal = function () { - transform = [1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1]; - }, - - updateSize = function () { - if (container && graphicsRoot) { - width = graphicsRoot.width = Math.max(container.offsetWidth, 1); - height = graphicsRoot.height = Math.max(container.offsetHeight, 1); - if (gl) { gl.viewport(0, 0, width, height); } - if (linkProgram) { linkProgram.updateSize(width / 2, height / 2); } - if (nodeProgram) { nodeProgram.updateSize(width / 2, height / 2); } - } - }, - - fireRescaled = function (graphics) { - graphics.fire("rescaled"); - }; - - graphicsRoot = window.document.createElement("canvas"); - - var graphics = { - getLinkUI: function (linkId) { - return allLinks[linkId]; - }, - - getNodeUI: function (nodeId) { - return allNodes[nodeId]; - }, - - /** - * Sets the callback that creates node representation. - * - * @param builderCallback a callback function that accepts graph node - * as a parameter and must return an element representing this node. - * - * @returns If builderCallbackOrNode is a valid callback function, instance of this is returned; - * Otherwise undefined value is returned - */ - node : function (builderCallback) { - if (typeof builderCallback !== "function") { - return; // todo: throw? This is not compatible with old versions - } - - nodeUIBuilder = builderCallback; - - return this; - }, - - /** - * Sets the callback that creates link representation - * - * @param builderCallback a callback function that accepts graph link - * as a parameter and must return an element representing this link. - * - * @returns If builderCallback is a valid callback function, instance of this is returned; - * Otherwise undefined value is returned. - */ - link : function (builderCallback) { - if (typeof builderCallback !== "function") { - return; // todo: throw? This is not compatible with old versions - } - - linkUIBuilder = builderCallback; - return this; - }, - - - /** - * Allows to override default position setter for the node with a new - * function. newPlaceCallback(nodeUI, position) is function which - * is used by updateNodePosition(). - */ - placeNode : function (newPlaceCallback) { - userPlaceNodeCallback = newPlaceCallback; - return this; - }, - - placeLink : function (newPlaceLinkCallback) { - userPlaceLinkCallback = newPlaceLinkCallback; - return this; - }, - - /** - * Custom input manager listens to mouse events to process nodes drag-n-drop inside WebGL canvas - */ - inputManager : webglInputManager, - - /** - * Called every time before renderer starts rendering. - */ - beginRender : function () { - // this function could be replaced by this.init, - // based on user options. - }, - - /** - * Called every time when renderer finishes one step of rendering. - */ - endRender : function () { - if (linksCount > 0) { - linkProgram.render(); - } - if (nodesCount > 0) { - nodeProgram.render(); - } - }, - - bringLinkToFront : function (linkUI) { - var frontLinkId = linkProgram.getFrontLinkId(), - srcLinkId, - temp; - - linkProgram.bringToFront(linkUI); - - if (frontLinkId > linkUI.id) { - srcLinkId = linkUI.id; - - temp = links[frontLinkId]; - links[frontLinkId] = links[srcLinkId]; - links[frontLinkId].id = frontLinkId; - links[srcLinkId] = temp; - links[srcLinkId].id = srcLinkId; - } - }, - - /** - * Sets translate operation that should be applied to all nodes and links. - */ - graphCenterChanged : function (x, y) { - transform[12] = (2 * x / width) - 1; - transform[13] = 1 - (2 * y / height); - updateTransformUniform(); - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render given link of the graph - * - * @param link - model of a link - */ - addLink: function (link, boundPosition) { - var uiid = linksCount++, - ui = linkUIBuilder(link); - ui.id = uiid; - ui.pos = boundPosition; - - linkProgram.createLink(ui); - - links[uiid] = ui; - allLinks[link.id] = ui; - return ui; - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render given node of the graph. - * - * @param nodeUI visual representation of the node created by node() execution. - **/ - addNode : function (node, boundPosition) { - var uiid = nodesCount++, - ui = nodeUIBuilder(node); - - ui.id = uiid; - ui.position = boundPosition; - ui.node = node; - - nodeProgram.createNode(ui); - - nodes[uiid] = ui; - allNodes[node.id] = ui; - return ui; - }, - - translateRel : function (dx, dy) { - transform[12] += (2 * transform[0] * dx / width) / transform[0]; - transform[13] -= (2 * transform[5] * dy / height) / transform[5]; - updateTransformUniform(); - }, - - scale : function (scaleFactor, scrollPoint) { - // Transform scroll point to clip-space coordinates: - var cx = 2 * scrollPoint.x / width - 1, - cy = 1 - (2 * scrollPoint.y) / height; - - cx -= transform[12]; - cy -= transform[13]; - - transform[12] += cx * (1 - scaleFactor); - transform[13] += cy * (1 - scaleFactor); - - transform[0] *= scaleFactor; - transform[5] *= scaleFactor; - - updateTransformUniform(); - fireRescaled(this); - - return transform[0]; - }, - - resetScale : function () { - resetScaleInternal(); - - if (gl) { - updateSize(); - // TODO: what is this? - // gl.useProgram(linksProgram); - // gl.uniform2f(linksProgram.screenSize, width, height); - updateTransformUniform(); - } - return this; - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render. - */ - init : function (c) { - var contextParameters = {}; - - if (options.preserveDrawingBuffer) { - contextParameters.preserveDrawingBuffer = true; - } - - container = c; - - updateSize(); - resetScaleInternal(); - container.appendChild(graphicsRoot); - - - gl = graphicsRoot.getContext("experimental-webgl", contextParameters); - if (!gl) { - var msg = "Could not initialize WebGL. Seems like the browser doesn't support it."; - window.alert(msg); - throw msg; - } - if (options.enableBlending) { - gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); - gl.enable(gl.BLEND); - } - if (options.clearColor) { - var color = options.clearColorValue; - gl.clearColor(color.r, color.g, color.b, color.a); - // TODO: not the best way, really. Should come up with something better - // what if we need more updates inside beginRender, like depth buffer? - this.beginRender = function () { - gl.clear(gl.COLOR_BUFFER_BIT); - }; - } - - linkProgram.load(gl); - linkProgram.updateSize(width / 2, height / 2); - - nodeProgram.load(gl); - nodeProgram.updateSize(width / 2, height / 2); - - updateTransformUniform(); - - // Notify the world if someone waited for update. TODO: should send an event - if (typeof initCallback === "function") { - initCallback(graphicsRoot); - } - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider release occupied resources. - */ - release : function (container) { - if (graphicsRoot && container) { - container.removeChild(graphicsRoot); - // TODO: anything else? - } - }, - - /** - * Checks whether webgl is supported by this browser. - */ - isSupported : function () { - var c = window.document.createElement("canvas"), - gl = c && c.getContext && c.getContext("experimental-webgl"); - return gl; - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider remove link from rendering surface. - * - * @param linkUI visual representation of the link created by link() execution. - **/ - releaseLink : function (link) { - if (linksCount > 0) { linksCount -= 1; } - var linkUI = allLinks[link.id]; - delete allLinks[link.id]; - - linkProgram.removeLink(linkUI); - - var linkIdToRemove = linkUI.id; - if (linkIdToRemove < linksCount) { - if (linksCount === 0 || linksCount === linkIdToRemove) { - return; // no more links or removed link is the last one. - } - - var lastLinkUI = links[linksCount]; - links[linkIdToRemove] = lastLinkUI; - lastLinkUI.id = linkIdToRemove; - } - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider remove node from rendering surface. - * - * @param nodeUI visual representation of the node created by node() execution. - **/ - releaseNode : function (node) { - if (nodesCount > 0) { nodesCount -= 1; } - var nodeUI = allNodes[node.id]; - delete allNodes[node.id]; - - nodeProgram.removeNode(nodeUI); - - var nodeIdToRemove = nodeUI.id; - if (nodeIdToRemove < nodesCount) { - if (nodesCount === 0 || nodesCount === nodeIdToRemove) { - return; // no more nodes or removed node is the last in the list. - } - - var lastNodeUI = nodes[nodesCount]; - - nodes[nodeIdToRemove] = lastNodeUI; - lastNodeUI.id = nodeIdToRemove; - - // Since concrete shaders may cache properties in the UI element - // we are letting them to make this swap (e.g. image node shader - // uses this approach to update node's offset in the atlas) - nodeProgram.replaceProperties(nodeUI, lastNodeUI); - } - }, - - renderNodes: function () { - var pos = {x : 0, y : 0}; - // WebGL coordinate system is different. Would be better - // to have this transform in the shader code, but it would - // require every shader to be updated.. - for (var i = 0; i < nodesCount; ++i) { - var ui = nodes[i]; - pos.x = ui.position.x; - pos.y = -ui.position.y; - if (userPlaceNodeCallback) { - userPlaceNodeCallback(ui, pos); - } - - nodeProgram.position(ui, pos); - } - }, - - renderLinks: function () { - if (this.omitLinksRendering) { return; } - - var toPos = {x : 0, y : 0}; - var fromPos = {x : 0, y : 0}; - for (var i = 0; i < linksCount; ++i) { - var ui = links[i]; - var pos = ui.pos.from; - fromPos.x = pos.x; - fromPos.y = -pos.y; - pos = ui.pos.to; - toPos.x = pos.x; - toPos.y = -pos.y; - if (userPlaceLinkCallback) { - userPlaceLinkCallback(ui, fromPos, toPos); - } - - linkProgram.position(ui, fromPos, toPos); - } - }, - - /** - * Returns root element which hosts graphics. - */ - getGraphicsRoot : function (callbackWhenReady) { - // todo: should fire an event, instead of having this context. - if (typeof callbackWhenReady === "function") { - if (graphicsRoot) { - callbackWhenReady(graphicsRoot); - } else { - initCallback = callbackWhenReady; - } - } - return graphicsRoot; - }, - - /** - * Updates default shader which renders nodes - * - * @param newProgram to use for nodes. - */ - setNodeProgram : function (newProgram) { - if (!gl && newProgram) { - // Nothing created yet. Just set shader to the new one - // and let initialization logic take care about the rest. - nodeProgram = newProgram; - } else if (newProgram) { - throw "Not implemented. Cannot swap shader on the fly... Yet."; - // TODO: unload old shader and reinit. - } - }, - - /** - * Updates default shader which renders links - * - * @param newProgram to use for links. - */ - setLinkProgram : function (newProgram) { - if (!gl && newProgram) { - // Nothing created yet. Just set shader to the new one - // and let initialization logic take care about the rest. - linkProgram = newProgram; - } else if (newProgram) { - throw "Not implemented. Cannot swap shader on the fly... Yet."; - // TODO: unload old shader and reinit. - } - }, - transformClientToGraphCoordinates : function (graphicsRootPos) { - // TODO: could be a problem when container has margins? - // to save memory we modify incoming parameter: - // point in clipspace coordinates: - graphicsRootPos.x = 2 * graphicsRootPos.x / width - 1; - graphicsRootPos.y = 1 - (2 * graphicsRootPos.y) / height; - // apply transform: - graphicsRootPos.x = (graphicsRootPos.x - transform[12]) / transform[0]; - graphicsRootPos.y = (graphicsRootPos.y - transform[13]) / transform[5]; - // now transform to graph coordinates: - graphicsRootPos.x *= width / 2; - graphicsRootPos.y *= -height / 2; - - return graphicsRootPos; - }, - - getNodeAtClientPos: function (clientPos, preciseCheck) { - if (typeof preciseCheck !== "function") { - // we don't know anything about your node structure here :( - // potentially this could be delegated to node program, but for - // right now, we are giving up if you don't pass boundary check - // callback. It answers to a question is nodeUI covers (x, y) - return null; - } - // first transform to graph coordinates: - this.transformClientToGraphCoordinates(clientPos); - // now using precise check iterate over each node and find one within box: - // TODO: This is poor O(N) performance. - for (var i = 0; i < nodesCount; ++i) { - if (preciseCheck(nodes[i], clientPos.x, clientPos.y)) { - return nodes[i].node; - } - } - return null; - } - }; - - // Let graphics fire events before we return it to the caller. - eventify(graphics); - - return graphics; -} +/** + * @fileOverview Defines a graph renderer that uses WebGL based drawings. + * + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka + */ + +module.exports = webglGraphics; + +var webglInputManager = require('../Input/webglInputManager.js'); +var webglLinkProgram = require('../WebGL/webglLinkProgram.js'); +var webglNodeProgram = require('../WebGL/webglNodeProgram.js'); +var webglSquare = require('../WebGL/webglSquare.js'); +var webglLine = require('../WebGL/webglLine.js'); +var eventify = require('ngraph.events'); +var merge = require('ngraph.merge'); + +/** + * Performs webgl-based graph rendering. This module does not perform + * layout, but only visualizes nodes and edges of the graph. + * + * @param options - to customize graphics behavior. Currently supported parameter + * enableBlending - true by default, allows to use transparency in node/links colors. + * preserveDrawingBuffer - false by default, tells webgl to preserve drawing buffer. + * See https://www.khronos.org/registry/webgl/specs/1.0/#5.2 + */ + +function webglGraphics(options) { + options = merge(options, { + enableBlending : true, + preserveDrawingBuffer : false, + clearColor: false, + clearColorValue : { + r : 1, + g : 1, + b : 1, + a : 1 + } + }); + + var container, + graphicsRoot, + gl, + width, + height, + nodesCount = 0, + linksCount = 0, + transform = [ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + ], + userPlaceNodeCallback, + userPlaceLinkCallback, + nodes = [], + links = [], + initCallback, + + allNodes = {}, + allLinks = {}, + linkProgram = webglLinkProgram(), + nodeProgram = webglNodeProgram(), +/*jshint unused: false */ + nodeUIBuilder = function (node) { + return webglSquare(); // Just make a square, using provided gl context (a nodeProgram); + }, + + linkUIBuilder = function (link) { + return webglLine(0xb3b3b3ff); + }, +/*jshint unused: true */ + updateTransformUniform = function () { + linkProgram.updateTransform(transform); + nodeProgram.updateTransform(transform); + }, + + resetScaleInternal = function () { + transform = [1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]; + }, + + updateSize = function () { + if (container && graphicsRoot) { + width = graphicsRoot.width = Math.max(container.offsetWidth, 1); + height = graphicsRoot.height = Math.max(container.offsetHeight, 1); + if (gl) { gl.viewport(0, 0, width, height); } + if (linkProgram) { linkProgram.updateSize(width / 2, height / 2); } + if (nodeProgram) { nodeProgram.updateSize(width / 2, height / 2); } + } + }, + + fireRescaled = function (graphics) { + graphics.fire("rescaled"); + }; + + graphicsRoot = window.document.createElement("canvas"); + + var graphics = { + getLinkUI: function (linkId) { + return allLinks[linkId]; + }, + + getNodeUI: function (nodeId) { + return allNodes[nodeId]; + }, + + /** + * Sets the callback that creates node representation. + * + * @param builderCallback a callback function that accepts graph node + * as a parameter and must return an element representing this node. + * + * @returns If builderCallbackOrNode is a valid callback function, instance of this is returned; + * Otherwise undefined value is returned + */ + node : function (builderCallback) { + if (typeof builderCallback !== "function") { + return; // todo: throw? This is not compatible with old versions + } + + nodeUIBuilder = builderCallback; + + return this; + }, + + /** + * Sets the callback that creates link representation + * + * @param builderCallback a callback function that accepts graph link + * as a parameter and must return an element representing this link. + * + * @returns If builderCallback is a valid callback function, instance of this is returned; + * Otherwise undefined value is returned. + */ + link : function (builderCallback) { + if (typeof builderCallback !== "function") { + return; // todo: throw? This is not compatible with old versions + } + + linkUIBuilder = builderCallback; + return this; + }, + + + /** + * Allows to override default position setter for the node with a new + * function. newPlaceCallback(nodeUI, position) is function which + * is used by updateNodePosition(). + */ + placeNode : function (newPlaceCallback) { + userPlaceNodeCallback = newPlaceCallback; + return this; + }, + + placeLink : function (newPlaceLinkCallback) { + userPlaceLinkCallback = newPlaceLinkCallback; + return this; + }, + + /** + * Custom input manager listens to mouse events to process nodes drag-n-drop inside WebGL canvas + */ + inputManager : webglInputManager, + + /** + * Called every time before renderer starts rendering. + */ + beginRender : function () { + // this function could be replaced by this.init, + // based on user options. + }, + + /** + * Called every time when renderer finishes one step of rendering. + */ + endRender : function () { + if (linksCount > 0) { + linkProgram.render(); + } + if (nodesCount > 0) { + nodeProgram.render(); + } + }, + + bringLinkToFront : function (linkUI) { + var frontLinkId = linkProgram.getFrontLinkId(), + srcLinkId, + temp; + + linkProgram.bringToFront(linkUI); + + if (frontLinkId > linkUI.id) { + srcLinkId = linkUI.id; + + temp = links[frontLinkId]; + links[frontLinkId] = links[srcLinkId]; + links[frontLinkId].id = frontLinkId; + links[srcLinkId] = temp; + links[srcLinkId].id = srcLinkId; + } + }, + + /** + * Sets translate operation that should be applied to all nodes and links. + */ + graphCenterChanged : function (x, y) { + transform[12] = (2 * x / width) - 1; + transform[13] = 1 - (2 * y / height); + updateTransformUniform(); + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render given link of the graph + * + * @param link - model of a link + */ + addLink: function (link, boundPosition) { + var uiid = linksCount++, + ui = linkUIBuilder(link); + ui.id = uiid; + ui.pos = boundPosition; + + linkProgram.createLink(ui); + + links[uiid] = ui; + allLinks[link.id] = ui; + return ui; + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render given node of the graph. + * + * @param nodeUI visual representation of the node created by node() execution. + **/ + addNode : function (node, boundPosition) { + var uiid = nodesCount++, + ui = nodeUIBuilder(node); + + ui.id = uiid; + ui.position = boundPosition; + ui.node = node; + + nodeProgram.createNode(ui); + + nodes[uiid] = ui; + allNodes[node.id] = ui; + return ui; + }, + + translateRel : function (dx, dy) { + transform[12] += (2 * transform[0] * dx / width) / transform[0]; + transform[13] -= (2 * transform[5] * dy / height) / transform[5]; + updateTransformUniform(); + }, + + scale : function (scaleFactor, scrollPoint) { + // Transform scroll point to clip-space coordinates: + var cx = 2 * scrollPoint.x / width - 1, + cy = 1 - (2 * scrollPoint.y) / height; + + cx -= transform[12]; + cy -= transform[13]; + + transform[12] += cx * (1 - scaleFactor); + transform[13] += cy * (1 - scaleFactor); + + transform[0] *= scaleFactor; + transform[5] *= scaleFactor; + + updateTransformUniform(); + fireRescaled(this); + + return transform[0]; + }, + + resetScale : function () { + resetScaleInternal(); + + if (gl) { + updateSize(); + // TODO: what is this? + // gl.useProgram(linksProgram); + // gl.uniform2f(linksProgram.screenSize, width, height); + updateTransformUniform(); + } + return this; + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render. + */ + init : function (c) { + var contextParameters = {}; + + if (options.preserveDrawingBuffer) { + contextParameters.preserveDrawingBuffer = true; + } + + container = c; + + updateSize(); + resetScaleInternal(); + container.appendChild(graphicsRoot); + + + gl = graphicsRoot.getContext("experimental-webgl", contextParameters); + if (!gl) { + var msg = "Could not initialize WebGL. Seems like the browser doesn't support it."; + window.alert(msg); + throw msg; + } + if (options.enableBlending) { + gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); + gl.enable(gl.BLEND); + } + if (options.clearColor) { + var color = options.clearColorValue; + gl.clearColor(color.r, color.g, color.b, color.a); + // TODO: not the best way, really. Should come up with something better + // what if we need more updates inside beginRender, like depth buffer? + this.beginRender = function () { + gl.clear(gl.COLOR_BUFFER_BIT); + }; + } + + linkProgram.load(gl); + linkProgram.updateSize(width / 2, height / 2); + + nodeProgram.load(gl); + nodeProgram.updateSize(width / 2, height / 2); + + updateTransformUniform(); + + // Notify the world if someone waited for update. TODO: should send an event + if (typeof initCallback === "function") { + initCallback(graphicsRoot); + } + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider release occupied resources. + */ + release : function (container) { + if (graphicsRoot && container) { + container.removeChild(graphicsRoot); + // TODO: anything else? + } + }, + + /** + * Checks whether webgl is supported by this browser. + */ + isSupported : function () { + var c = window.document.createElement("canvas"), + gl = c && c.getContext && c.getContext("experimental-webgl"); + return gl; + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider remove link from rendering surface. + * + * @param linkUI visual representation of the link created by link() execution. + **/ + releaseLink : function (link) { + if (linksCount > 0) { linksCount -= 1; } + var linkUI = allLinks[link.id]; + delete allLinks[link.id]; + + linkProgram.removeLink(linkUI); + + var linkIdToRemove = linkUI.id; + if (linkIdToRemove < linksCount) { + if (linksCount === 0 || linksCount === linkIdToRemove) { + return; // no more links or removed link is the last one. + } + + var lastLinkUI = links[linksCount]; + links[linkIdToRemove] = lastLinkUI; + lastLinkUI.id = linkIdToRemove; + } + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider remove node from rendering surface. + * + * @param nodeUI visual representation of the node created by node() execution. + **/ + releaseNode : function (node) { + if (nodesCount > 0) { nodesCount -= 1; } + var nodeUI = allNodes[node.id]; + delete allNodes[node.id]; + + nodeProgram.removeNode(nodeUI); + + var nodeIdToRemove = nodeUI.id; + if (nodeIdToRemove < nodesCount) { + if (nodesCount === 0 || nodesCount === nodeIdToRemove) { + return; // no more nodes or removed node is the last in the list. + } + + var lastNodeUI = nodes[nodesCount]; + + nodes[nodeIdToRemove] = lastNodeUI; + lastNodeUI.id = nodeIdToRemove; + + // Since concrete shaders may cache properties in the UI element + // we are letting them to make this swap (e.g. image node shader + // uses this approach to update node's offset in the atlas) + nodeProgram.replaceProperties(nodeUI, lastNodeUI); + } + }, + + renderNodes: function () { + var pos = {x : 0, y : 0}; + // WebGL coordinate system is different. Would be better + // to have this transform in the shader code, but it would + // require every shader to be updated.. + for (var i = 0; i < nodesCount; ++i) { + var ui = nodes[i]; + pos.x = ui.position.x; + pos.y = -ui.position.y; + if (userPlaceNodeCallback) { + userPlaceNodeCallback(ui, pos); + } + + nodeProgram.position(ui, pos); + } + }, + + renderLinks: function () { + if (this.omitLinksRendering) { return; } + + var toPos = {x : 0, y : 0}; + var fromPos = {x : 0, y : 0}; + for (var i = 0; i < linksCount; ++i) { + var ui = links[i]; + var pos = ui.pos.from; + fromPos.x = pos.x; + fromPos.y = -pos.y; + pos = ui.pos.to; + toPos.x = pos.x; + toPos.y = -pos.y; + if (userPlaceLinkCallback) { + userPlaceLinkCallback(ui, fromPos, toPos); + } + + linkProgram.position(ui, fromPos, toPos); + } + }, + + /** + * Returns root element which hosts graphics. + */ + getGraphicsRoot : function (callbackWhenReady) { + // todo: should fire an event, instead of having this context. + if (typeof callbackWhenReady === "function") { + if (graphicsRoot) { + callbackWhenReady(graphicsRoot); + } else { + initCallback = callbackWhenReady; + } + } + return graphicsRoot; + }, + + /** + * Updates default shader which renders nodes + * + * @param newProgram to use for nodes. + */ + setNodeProgram : function (newProgram) { + if (!gl && newProgram) { + // Nothing created yet. Just set shader to the new one + // and let initialization logic take care about the rest. + nodeProgram = newProgram; + } else if (newProgram) { + throw "Not implemented. Cannot swap shader on the fly... Yet."; + // TODO: unload old shader and reinit. + } + }, + + /** + * Updates default shader which renders links + * + * @param newProgram to use for links. + */ + setLinkProgram : function (newProgram) { + if (!gl && newProgram) { + // Nothing created yet. Just set shader to the new one + // and let initialization logic take care about the rest. + linkProgram = newProgram; + } else if (newProgram) { + throw "Not implemented. Cannot swap shader on the fly... Yet."; + // TODO: unload old shader and reinit. + } + }, + transformClientToGraphCoordinates : function (graphicsRootPos) { + // TODO: could be a problem when container has margins? + // to save memory we modify incoming parameter: + // point in clipspace coordinates: + graphicsRootPos.x = 2 * graphicsRootPos.x / width - 1; + graphicsRootPos.y = 1 - (2 * graphicsRootPos.y) / height; + // apply transform: + graphicsRootPos.x = (graphicsRootPos.x - transform[12]) / transform[0]; + graphicsRootPos.y = (graphicsRootPos.y - transform[13]) / transform[5]; + // now transform to graph coordinates: + graphicsRootPos.x *= width / 2; + graphicsRootPos.y *= -height / 2; + + return graphicsRootPos; + }, + + getNodeAtClientPos: function (clientPos, preciseCheck) { + if (typeof preciseCheck !== "function") { + // we don't know anything about your node structure here :( + // potentially this could be delegated to node program, but for + // right now, we are giving up if you don't pass boundary check + // callback. It answers to a question is nodeUI covers (x, y) + return null; + } + // first transform to graph coordinates: + this.transformClientToGraphCoordinates(clientPos); + // now using precise check iterate over each node and find one within box: + // TODO: This is poor O(N) performance. + for (var i = 0; i < nodesCount; ++i) { + if (preciseCheck(nodes[i], clientPos.x, clientPos.y)) { + return nodes[i].node; + } + } + return null; + } + }; + + // Let graphics fire events before we return it to the caller. + eventify(graphics); + + return graphics; +} },{"../Input/webglInputManager.js":37,"../WebGL/webglLine.js":59,"../WebGL/webglLinkProgram.js":60,"../WebGL/webglNodeProgram.js":61,"../WebGL/webglSquare.js":62,"ngraph.events":6,"ngraph.merge":25}],52:[function(require,module,exports){ module.exports = parseColor; @@ -6852,7 +6852,7 @@ function webglSquare(size, color) { },{"./parseColor.js":52}],63:[function(require,module,exports){ // todo: this should be generated at build time. -module.exports = '0.7.8'; +module.exports = '0.7.9'; },{}]},{},[1])(1) }); \ No newline at end of file diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 39a1515..00e7a23 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-s*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=t},{}],3:[function(e,n){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n){function t(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function g(e){var n=w[e];n.mass=y(e)}function h(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function m(e){var n=w[e];return n||(c(e),n=w[e]),n}function y(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var x=e("ngraph.physics.simulator");t=t||x(),o(t,"physicsSimulator").has("step","getBestNewBodyPosition","addBodyAt");var w="function"==typeof Object.create?Object.create(null):{},b={},E=t.settings.springTransform||r;f(),u();var L={step:function(){return t.step()},getNodePosition:function(e){return m(e).pos},setNodePosition:function(e){var n=m(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return t.getBBox()},pinNode:function(e,n){var t=m(e.id);t.isPinned=!!n},isNodePinned:function(e){return m(e.id).isPinned},dispose:function(){n.off("changed",s)},getBody:a,getSpring:i,simulator:t};return L}function r(){}n.exports=t,n.exports.simulator=e("ngraph.physics.simulator");var o=e("varta")},{"ngraph.physics.simulator":8,varta:21}],8:[function(e,n){function t(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.force.reset(),v.updateBodyForce(e),m.update(e);for(n=p.length;n--;)h.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),u=n.createBounds||e("./lib/bounds"),s=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),g=u(l,n),h=f(n),m=s(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return g.update(),en))return l.splice(n,1),0===l.length&&g.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return g.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=t},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":25,"ngraph.quadtreebh":17}],9:[function(e,n){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;ut;++t){var s=e[t],f=n/s.mass;s.velocity.x+=f*s.force.x,s.velocity.y+=f*s.force.y;var c=s.velocity.x,d=s.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=t},{}],13:[function(e,n){function t(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=t},{}],14:[function(e,n){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":25,"ngraph.random":26}],15:[function(e,n){function t(e,n,t){var o="[object Array]"===Object.prototype.toString.call(t);if(o)for(var i=0;i0&&u(s.pos,a.pos));if(0===f&&u(s.pos,a.pos))return}c.push(i,s),c.push(i,a)}else{var h=a.pos.x,m=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*h,i.massY=i.massY+a.mass*m;var y=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;if(h>w){y+=1;var L=x;x=w,w+=w-L}if(m>E){y+=2;var P=b;b=E,E+=E-P}var N=t(i,y);N?c.push(N,a):(N=v(),N.left=x,N.top=b,N.right=w,N.bottom=E,N.body=a,r(i,y,N))}}},m=function(e){var n,t,r,i,a=f,u=0,c=0,l=1,p=0,v=1;for(a[0]=g;l;){var h=a[p],m=h.body;l-=1,p+=1;var y=m!==e;m&&y?(t=m.pos.x-e.pos.x,r=m.pos.y-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),n=s*m.mass*e.mass/(i*i*i),u+=n*t,c+=n*r):y&&(t=h.massX/h.mass-e.pos.x,r=h.massY/h.mass-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),(h.right-h.left)/iu&&(t=u),u>o&&(o=u),r>s&&(r=s),s>i&&(i=s)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,p=0,g=v(),g.left=t,g.right=o,g.top=r,g.bottom=i,n=a-1,n>0&&(g.body=e[n]);n--;)h(e[n],g)};return{insertBodies:y,updateBodyForce:m,options:function(e){return e?("number"==typeof e.gravity&&(s=e.gravity),"number"==typeof e.theta&&(d=e.theta),this):{gravity:s,theta:d}}}}},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":26}],18:[function(e,n){function t(){this.stack=[],this.popIdx=0}function r(e,n){this.node=e,this.body=n}n.exports=t,t.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new r(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],19:[function(e,n){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],20:[function(e,n){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],21:[function(e,n){function t(e,n){function t(){return o(e,n,arguments)}return n=n||"Argument",{has:t}}function r(){function e(e,t){return o(e,t,n)}var n=arguments;return e}function o(e,n,t){if(void 0===e)throw new Error(n+" is not defined");for(var r=0;re)throw new Error("Invalid number of nodes");var n,t=l();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function r(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=t(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function o(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=l();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function i(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=l();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function a(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=l();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function u(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=l();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function s(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=l();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var u=i*e*n,s=r+o*e+u;r>0&&a.addLink(s,r-1+o*e+u),o>0&&a.addLink(s,r+(o-1)*e+u),i>0&&a.addLink(s,r+o*e+(i-1)*e*n)}return a}function f(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=l(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function c(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=l();for(n=0;e>n;++n)t.addNode(n);return t}function d(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,u=e("ngraph.random").random(o||42),s=l();for(i=0;n>i;++i)s.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,s.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(u.nextDouble()n)return!1;B(),_.splice(n,1);var t=f(e.fromId),o=f(e.toId);return t&&(n=r(e,t.links),n>=0&&t.links.splice(n,1)),o&&(n=r(e,o.links),n>=0&&o.links.splice(n,1)),U(e,"remove"),F(),!0}function h(e,n){var t,r=f(e);if(!r)return null;for(t=0;tn;++n)e(_[n])}function x(e,n,t){var r=f(e);return r&&r.links&&"function"==typeof n?t?b(r.links,e,n):w(r.links,e,n):void 0}function w(e,n,t){for(var r,o=0;o0&&(O.fire("changed",M),M.length=0)}function N(){return Object.keys?k:A}function k(e){if("function"==typeof e)for(var n=Object.keys(j),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function o(e){this.id=e,this.links=[],this.data=null}function i(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=t;var a=e("ngraph.events")},{"ngraph.events":6}],25:[function(e,n){function t(e,n){var r;if(e||(e={}),n)for(r in n)if(n.hasOwnProperty(r)){var o=e.hasOwnProperty(r),i=typeof n[r],a=!o||typeof e[r]!==i;a?e[r]=n[r]:"object"===i&&(e[r]=t(e[r],n[r]))}return e}n.exports=t},{}],26:[function(e,n){function t(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function r(e,n){var r=n||t();if("function"!=typeof r.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var t,o,i;for(t=e.length-1;t>0;--t)o=r.next(t+1),i=e[o],e[o]=e[t],e[t]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,t,o;for(n=e.length-1;n>0;--n)t=r.next(n+1),o=e[t],e[t]=e[n],e[n]=o;return e}}}n.exports={random:t,randomIterator:r}},{}],27:[function(e,n){function t(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=t},{}],28:[function(e,n){function t(e,n){var t=r(e);if(void 0===n)return t;for(var o=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},A=function(e){p=!1,r.off("touchmove",k),r.off("touchend",A),r.off("touchcancel",A),c=null,a&&a(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,r.on("touchmove",k),r.on("touchend",A),r.on("touchcancel",A)) -},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return a=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),r.off("mousemove",w),r.off("mouseup",E),r.off("touchmove",k),r.off("touchend",A),r.off("touchcancel",A),P(null)}}}n.exports=t;var r=e("../Utils/documentEvents.js"),o=e("../Utils/browserInfo.js"),i=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":40,"../Utils/documentEvents.js":41,"../Utils/findElementPosition.js":42}],37:[function(e,n){function t(e,n){var t=r(n),o=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){o=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(o);var r=i[e.id];return r&&r.onStart&&r.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(o),o=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(o){var t=i[o.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=t;var r=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":58}],38:[function(e,n){function t(e,n){function t(e){return d[e]}n=r(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var a=o(n.seed),u=new i(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(){return{x:a.next(n.maxX),y:a.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"==typeof z?z:!0}function d(){G=G||window.document.body,F=F||o(e,o.simulator({springLength:80,springCoeff:2e-4})),O=O||i(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||u)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=s(function(){return p()},M)):(X=0,V=0,R=s(p,M)))}function g(){J||(W=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;en,t)}),e.forEachNode(E),T(),e.on("changed",j)}function D(){q=!1,T(),I(),a.off("resize",_),Q.off(),R.stop(),e.forEachLink(function(e){n.renderLinks&&b(e)}),e.forEachNode(function(e){L(e),x(e)}),F.dispose(),N()}var M=30;n=n||{};var U,R,B,F=n.layout,O=n.graphics,G=n.container,z=void 0!==n.interactive?n.interactive:!0,q=!1,Y=!0,X=0,V=0,W=!1,H=!1,J=!1,$={x:0,y:0},K={offsetX:0,offsetY:0,scale:1},Q=r({});return{run:function(e){return q||(d(),h(),m(),P(),S(),q=!0),v(e),this},reset:function(){O.resetScale(),m(),K.scale=1},pause:function(){J=!0,R.stop()},resume:function(){J=!1,R.restart()},rerender:function(){return l(),this},zoomOut:function(){return C(!0)},zoomIn:function(){return C(!1)},moveTo:function(e,n){O.graphCenterChanged(K.offsetX-e*K.scale,K.offsetY-n*K.scale),l()},getGraphics:function(){return O},dispose:function(){D()},on:function(e,n){return Q.on(e,n),this},off:function(e,n){return Q.off(e,n),this}}}n.exports=t;var r=e("ngraph.events"),o=e("ngraph.forcelayout"),i=e("./svgGraphics.js"),a=e("../Utils/windowEvents.js"),u=e("../Input/domInputManager.js"),s=e("../Utils/timer.js"),f=e("../Utils/getDimensions.js"),c=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.events":6,"ngraph.forcelayout":7}],50:[function(e,n){function t(){function e(){var e=r("svg");return n=r("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,a,u,s,f=1,c={},d={},l=function(){return r("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(){return r("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+a+","+u+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){a=e,u=n,w()},inputManager:i,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),s=n.getCTM().multiply(i);f=s.a,a=s.e,u=s.f;var c="matrix("+s.a+", 0, 0,"+s.d+","+s.e+","+s.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof s&&s(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):s=e),t},getSvgRoot:function(){return t}};return o(b),b}n.exports=t;var r=e("simplesvg"),o=e("ngraph.events"),i=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":35,"ngraph.events":6,simplesvg:28}],51:[function(e,n){function t(e){e=f(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,c,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=o(),P=i(),N=function(){return a()},k=function(){return u(3014898687)},A=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),c&&c.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(k=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:r,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,A()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],A()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,A(),I(this),y[0]},resetScale:function(){return j(),c&&(_(),A()),this},init:function(r){var o={};if(e.preserveDrawingBuffer&&(o.preserveDrawingBuffer=!0),n=r,_(),j(),n.appendChild(t),c=t.getContext("experimental-webgl",o),!c){var i="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(i),i}if(e.enableBlending&&(c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA),c.enable(c.BLEND)),e.clearColor){var a=e.clearColorValue;c.clearColor(a.r,a.g,a.b,a.a),this.beginRender=function(){c.clear(c.COLOR_BUFFER_BIT)}}L.load(c),L.updateSize(d/2,l/2),P.load(c),P.updateSize(d/2,l/2),A(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!c&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!c&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return s(T),T}n.exports=t;var r=e("../Input/webglInputManager.js"),o=e("../WebGL/webglLinkProgram.js"),i=e("../WebGL/webglNodeProgram.js"),a=e("../WebGL/webglSquare.js"),u=e("../WebGL/webglLine.js"),s=e("ngraph.events"),f=e("ngraph.merge")},{"../Input/webglInputManager.js":37,"../WebGL/webglLine.js":59,"../WebGL/webglLinkProgram.js":60,"../WebGL/webglNodeProgram.js":61,"../WebGL/webglSquare.js":62,"ngraph.events":6,"ngraph.merge":25}],52:[function(e,n){function t(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=t},{}],53:[function(e,n){function t(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=t},{}],54:[function(e,n){function t(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function i(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function o(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=t},{}],55:[function(e,n){function t(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!r(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:i,getCoordinates:a,load:u};return E}function r(e){return 0===(e&e-1)}var o=e("./texture.js");n.exports=t},{"./texture.js":53}],56:[function(e,n){function t(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=t},{}],57:[function(e,n){function t(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=r(),k=o(),A=1024,j=0,_=new Float32Array(64);return{load:t,position:u,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function r(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function o(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var i=e("./webglAtlas.js"),a=e("./webgl.js");n.exports=t},{"./webgl.js":54,"./webglAtlas.js":55}],58:[function(e,n){function t(e){function n(){x=null}function t(e){x=e}function o(e){return"function"==typeof e&&k.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(k,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],k=[],A=e.getGraphicsRoot();h(A);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:o,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var r=e("../Utils/documentEvents.js");n.exports=t},{"../Utils/documentEvents.js":41}],59:[function(e,n){function t(e){return{color:r(e)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],60:[function(e,n){function t(){var e,n,t,o,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,o=r(a),e=o.createProgram(v,p),n.useProgram(e),i=o.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&o.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&o.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],61:[function(e,n){function t(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=r(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function o(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(N,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:o,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],62:[function(e,n){function t(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],63:[function(e,n){n.exports="0.7.8"},{}]},{},[1])(1)}); \ No newline at end of file +},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return a=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),r.off("mousemove",w),r.off("mouseup",E),r.off("touchmove",k),r.off("touchend",A),r.off("touchcancel",A),P(null)}}}n.exports=t;var r=e("../Utils/documentEvents.js"),o=e("../Utils/browserInfo.js"),i=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":40,"../Utils/documentEvents.js":41,"../Utils/findElementPosition.js":42}],37:[function(e,n){function t(e,n){var t=r(n),o=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){o=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(o);var r=i[e.id];return r&&r.onStart&&r.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(o),o=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(o){var t=i[o.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=t;var r=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":58}],38:[function(e,n){function t(e,n){function t(e){return d[e]}n=r(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var a=o(n.seed),u=new i(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(){return{x:a.next(n.maxX),y:a.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"==typeof z?z:!0}function d(){G=G||window.document.body,F=F||o(e,o.simulator({springLength:80,springCoeff:2e-4})),O=O||i(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||u)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=s(function(){return p()},M)):(X=0,V=0,R=s(p,M)))}function g(){J||(W=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;en,t)}),e.forEachNode(E),T(),e.on("changed",j)}function D(){q=!1,T(),I(),a.off("resize",_),Q.off(),R.stop(),e.forEachLink(function(e){n.renderLinks&&b(e)}),e.forEachNode(function(e){L(e),x(e)}),F.dispose(),N()}var M=30;n=n||{};var U,R,B,F=n.layout,O=n.graphics,G=n.container,z=void 0!==n.interactive?n.interactive:!0,q=!1,Y=!0,X=0,V=0,W=!1,H=!1,J=!1,$={x:0,y:0},K={offsetX:0,offsetY:0,scale:1},Q=r({});return{run:function(e){return q||(d(),h(),m(),P(),S(),q=!0),v(e),this},reset:function(){O.resetScale(),m(),K.scale=1},pause:function(){J=!0,R.stop()},resume:function(){J=!1,R.restart()},rerender:function(){return l(),this},zoomOut:function(){return C(!0)},zoomIn:function(){return C(!1)},moveTo:function(e,n){O.graphCenterChanged(K.offsetX-e*K.scale,K.offsetY-n*K.scale),l()},getGraphics:function(){return O},dispose:function(){D()},on:function(e,n){return Q.on(e,n),this},off:function(e,n){return Q.off(e,n),this}}}n.exports=t;var r=e("ngraph.events"),o=e("ngraph.forcelayout"),i=e("./svgGraphics.js"),a=e("../Utils/windowEvents.js"),u=e("../Input/domInputManager.js"),s=e("../Utils/timer.js"),f=e("../Utils/getDimensions.js"),c=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.events":6,"ngraph.forcelayout":7}],50:[function(e,n){function t(){function e(){var e=r("svg");return n=r("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,a,u,s,f=1,c={},d={},l=function(){return r("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(){return r("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+a+","+u+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){a=e,u=n,w()},inputManager:i,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),s=n.getCTM().multiply(i);f=s.a,a=s.e,u=s.f;var c="matrix("+s.a+", 0, 0,"+s.d+","+s.e+","+s.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof s&&s(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):s=e),t},getSvgRoot:function(){return t}};return o(b),b}n.exports=t;var r=e("simplesvg"),o=e("ngraph.events"),i=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":35,"ngraph.events":6,simplesvg:28}],51:[function(e,n){function t(e){e=f(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,c,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=o(),P=i(),N=function(){return a()},k=function(){return u(3014898687)},A=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),c&&c.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(k=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:r,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,A()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],A()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,A(),I(this),y[0]},resetScale:function(){return j(),c&&(_(),A()),this},init:function(r){var o={};if(e.preserveDrawingBuffer&&(o.preserveDrawingBuffer=!0),n=r,_(),j(),n.appendChild(t),c=t.getContext("experimental-webgl",o),!c){var i="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(i),i}if(e.enableBlending&&(c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA),c.enable(c.BLEND)),e.clearColor){var a=e.clearColorValue;c.clearColor(a.r,a.g,a.b,a.a),this.beginRender=function(){c.clear(c.COLOR_BUFFER_BIT)}}L.load(c),L.updateSize(d/2,l/2),P.load(c),P.updateSize(d/2,l/2),A(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!c&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!c&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return s(T),T}n.exports=t;var r=e("../Input/webglInputManager.js"),o=e("../WebGL/webglLinkProgram.js"),i=e("../WebGL/webglNodeProgram.js"),a=e("../WebGL/webglSquare.js"),u=e("../WebGL/webglLine.js"),s=e("ngraph.events"),f=e("ngraph.merge")},{"../Input/webglInputManager.js":37,"../WebGL/webglLine.js":59,"../WebGL/webglLinkProgram.js":60,"../WebGL/webglNodeProgram.js":61,"../WebGL/webglSquare.js":62,"ngraph.events":6,"ngraph.merge":25}],52:[function(e,n){function t(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=t},{}],53:[function(e,n){function t(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=t},{}],54:[function(e,n){function t(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function i(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function o(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=t},{}],55:[function(e,n){function t(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!r(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:i,getCoordinates:a,load:u};return E}function r(e){return 0===(e&e-1)}var o=e("./texture.js");n.exports=t},{"./texture.js":53}],56:[function(e,n){function t(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=t},{}],57:[function(e,n){function t(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=r(),k=o(),A=1024,j=0,_=new Float32Array(64);return{load:t,position:u,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function r(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function o(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var i=e("./webglAtlas.js"),a=e("./webgl.js");n.exports=t},{"./webgl.js":54,"./webglAtlas.js":55}],58:[function(e,n){function t(e){function n(){x=null}function t(e){x=e}function o(e){return"function"==typeof e&&k.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(k,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],k=[],A=e.getGraphicsRoot();h(A);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:o,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var r=e("../Utils/documentEvents.js");n.exports=t},{"../Utils/documentEvents.js":41}],59:[function(e,n){function t(e){return{color:r(e)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],60:[function(e,n){function t(){var e,n,t,o,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,o=r(a),e=o.createProgram(v,p),n.useProgram(e),i=o.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&o.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&o.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],61:[function(e,n){function t(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=r(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function o(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(N,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:o,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],62:[function(e,n){function t(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],63:[function(e,n){n.exports="0.7.9"},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/src/version.js b/src/version.js index 032d133..8c50d1e 100644 --- a/src/version.js +++ b/src/version.js @@ -1,2 +1,2 @@ // todo: this should be generated at build time. -module.exports = '0.7.8'; +module.exports = '0.7.9'; From 0440da1859fed52b13b405c44abda253f0f03a61 Mon Sep 17 00:00:00 2001 From: anvaka Date: Thu, 9 Apr 2015 09:38:07 -0700 Subject: [PATCH 194/276] 0.7.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ef96717..54d108b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.7.8", + "version": "0.7.9", "description": "Graph Drawing Library", "main": "src/viva", "directories": { From d3c2a642e89418f15e84f2d40c76679ae894bd56 Mon Sep 17 00:00:00 2001 From: Andrei Kashcha Date: Fri, 10 Apr 2015 18:02:58 -0700 Subject: [PATCH 195/276] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 3b91ee7..954d058 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@ library for JavaScript. It is designed to be extensible and to support different rendering engines and layout algorithms. At the moment it supports rendering graphs using WebGL and SVG. +[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/anvaka/VivaGraphJS?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) + Enough talking. Show me the demo! ---------------------------------------------------- Some examples of library usage in the real projects: From 5ce728152d03b1ecdf1f939604c31ad8c138e1bb Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 12 Apr 2015 14:11:45 -0700 Subject: [PATCH 196/276] Removed unused code --- src/View/renderer.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/View/renderer.js b/src/View/renderer.js index ca0e6b3..0a81f5f 100644 --- a/src/View/renderer.js +++ b/src/View/renderer.js @@ -73,11 +73,6 @@ function renderer(graph, settings) { userInteraction = false, isPaused = false, - viewPortOffset = { - x: 0, - y: 0 - }, - transform = { offsetX: 0, offsetY: 0, @@ -103,8 +98,8 @@ function renderer(graph, settings) { prepareSettings(); prerender(); - updateCenter(); initDom(); + updateCenter(); listenToEvents(); rendererInitialized = true; @@ -267,7 +262,6 @@ function renderer(graph, settings) { var graphRect = layout.getGraphRect(), containerSize = getDimension(container); - viewPortOffset.x = viewPortOffset.y = 0; transform.offsetX = containerSize.width / 2 - (graphRect.x2 + graphRect.x1) / 2; transform.offsetY = containerSize.height / 2 - (graphRect.y2 + graphRect.y1) / 2; graphics.graphCenterChanged(transform.offsetX, transform.offsetY); @@ -436,8 +430,6 @@ function renderer(graph, settings) { if (isInteractive('drag')) { containerDrag = dragndrop(container); containerDrag.onDrag(function(e, offset) { - viewPortOffset.x += offset.x; - viewPortOffset.y += offset.y; graphics.translateRel(offset.x, offset.y); renderGraph(); From 20b62dae99a87fac747b63ac936343be4919bb09 Mon Sep 17 00:00:00 2001 From: anvaka Date: Mon, 13 Apr 2015 18:49:32 -0700 Subject: [PATCH 197/276] Fixed https://github.com/anvaka/VivaGraphJS/issues/136 --- dist/vivagraph.js | 22 ++++++++-------------- dist/vivagraph.min.js | 2 +- src/View/renderer.js | 6 ++++-- src/View/svgGraphics.js | 4 ++-- src/version.js | 2 +- 5 files changed, 16 insertions(+), 20 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 7fde7ba..4002285 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -4265,11 +4265,6 @@ function renderer(graph, settings) { userInteraction = false, isPaused = false, - viewPortOffset = { - x: 0, - y: 0 - }, - transform = { offsetX: 0, offsetY: 0, @@ -4295,8 +4290,8 @@ function renderer(graph, settings) { prepareSettings(); prerender(); - updateCenter(); initDom(); + updateCenter(); listenToEvents(); rendererInitialized = true; @@ -4459,9 +4454,10 @@ function renderer(graph, settings) { var graphRect = layout.getGraphRect(), containerSize = getDimension(container); - viewPortOffset.x = viewPortOffset.y = 0; - transform.offsetX = containerSize.width / 2 - (graphRect.x2 + graphRect.x1) / 2; - transform.offsetY = containerSize.height / 2 - (graphRect.y2 + graphRect.y1) / 2; + var cx = (graphRect.x2 + graphRect.x1) / 2; + var cy = (graphRect.y2 + graphRect.y1) / 2; + transform.offsetX = containerSize.width / 2 - (cx * transform.scale - cx); + transform.offsetY = containerSize.height / 2 - (cy * transform.scale - cy); graphics.graphCenterChanged(transform.offsetX, transform.offsetY); updateCenterRequired = false; @@ -4628,8 +4624,6 @@ function renderer(graph, settings) { if (isInteractive('drag')) { containerDrag = dragndrop(container); containerDrag.onDrag(function(e, offset) { - viewPortOffset.x += offset.x; - viewPortOffset.y += offset.y; graphics.translateRel(offset.x, offset.y); renderGraph(); @@ -4692,8 +4686,8 @@ var domInputManager = require('../Input/domInputManager.js'); function svgGraphics() { var svgContainer, svgRoot, - offsetX, - offsetY, + offsetX = 0, + offsetY = 0, initCallback, actualScale = 1, allNodes = {}, @@ -6852,7 +6846,7 @@ function webglSquare(size, color) { },{"./parseColor.js":52}],63:[function(require,module,exports){ // todo: this should be generated at build time. -module.exports = '0.7.9'; +module.exports = '0.7.10'; },{}]},{},[1])(1) }); \ No newline at end of file diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 00e7a23..7a99901 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-s*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=t},{}],3:[function(e,n){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n){function t(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function g(e){var n=w[e];n.mass=y(e)}function h(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function m(e){var n=w[e];return n||(c(e),n=w[e]),n}function y(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var x=e("ngraph.physics.simulator");t=t||x(),o(t,"physicsSimulator").has("step","getBestNewBodyPosition","addBodyAt");var w="function"==typeof Object.create?Object.create(null):{},b={},E=t.settings.springTransform||r;f(),u();var L={step:function(){return t.step()},getNodePosition:function(e){return m(e).pos},setNodePosition:function(e){var n=m(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return t.getBBox()},pinNode:function(e,n){var t=m(e.id);t.isPinned=!!n},isNodePinned:function(e){return m(e.id).isPinned},dispose:function(){n.off("changed",s)},getBody:a,getSpring:i,simulator:t};return L}function r(){}n.exports=t,n.exports.simulator=e("ngraph.physics.simulator");var o=e("varta")},{"ngraph.physics.simulator":8,varta:21}],8:[function(e,n){function t(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.force.reset(),v.updateBodyForce(e),m.update(e);for(n=p.length;n--;)h.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),u=n.createBounds||e("./lib/bounds"),s=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),g=u(l,n),h=f(n),m=s(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return g.update(),en))return l.splice(n,1),0===l.length&&g.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return g.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=t},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":25,"ngraph.quadtreebh":17}],9:[function(e,n){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;ut;++t){var s=e[t],f=n/s.mass;s.velocity.x+=f*s.force.x,s.velocity.y+=f*s.force.y;var c=s.velocity.x,d=s.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=t},{}],13:[function(e,n){function t(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=t},{}],14:[function(e,n){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":25,"ngraph.random":26}],15:[function(e,n){function t(e,n,t){var o="[object Array]"===Object.prototype.toString.call(t);if(o)for(var i=0;i0&&u(s.pos,a.pos));if(0===f&&u(s.pos,a.pos))return}c.push(i,s),c.push(i,a)}else{var h=a.pos.x,m=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*h,i.massY=i.massY+a.mass*m;var y=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;if(h>w){y+=1;var L=x;x=w,w+=w-L}if(m>E){y+=2;var P=b;b=E,E+=E-P}var N=t(i,y);N?c.push(N,a):(N=v(),N.left=x,N.top=b,N.right=w,N.bottom=E,N.body=a,r(i,y,N))}}},m=function(e){var n,t,r,i,a=f,u=0,c=0,l=1,p=0,v=1;for(a[0]=g;l;){var h=a[p],m=h.body;l-=1,p+=1;var y=m!==e;m&&y?(t=m.pos.x-e.pos.x,r=m.pos.y-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),n=s*m.mass*e.mass/(i*i*i),u+=n*t,c+=n*r):y&&(t=h.massX/h.mass-e.pos.x,r=h.massY/h.mass-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),(h.right-h.left)/iu&&(t=u),u>o&&(o=u),r>s&&(r=s),s>i&&(i=s)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,p=0,g=v(),g.left=t,g.right=o,g.top=r,g.bottom=i,n=a-1,n>0&&(g.body=e[n]);n--;)h(e[n],g)};return{insertBodies:y,updateBodyForce:m,options:function(e){return e?("number"==typeof e.gravity&&(s=e.gravity),"number"==typeof e.theta&&(d=e.theta),this):{gravity:s,theta:d}}}}},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":26}],18:[function(e,n){function t(){this.stack=[],this.popIdx=0}function r(e,n){this.node=e,this.body=n}n.exports=t,t.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new r(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],19:[function(e,n){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],20:[function(e,n){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],21:[function(e,n){function t(e,n){function t(){return o(e,n,arguments)}return n=n||"Argument",{has:t}}function r(){function e(e,t){return o(e,t,n)}var n=arguments;return e}function o(e,n,t){if(void 0===e)throw new Error(n+" is not defined");for(var r=0;re)throw new Error("Invalid number of nodes");var n,t=l();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function r(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=t(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function o(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=l();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function i(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=l();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function a(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=l();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function u(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=l();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function s(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=l();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var u=i*e*n,s=r+o*e+u;r>0&&a.addLink(s,r-1+o*e+u),o>0&&a.addLink(s,r+(o-1)*e+u),i>0&&a.addLink(s,r+o*e+(i-1)*e*n)}return a}function f(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=l(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function c(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=l();for(n=0;e>n;++n)t.addNode(n);return t}function d(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,u=e("ngraph.random").random(o||42),s=l();for(i=0;n>i;++i)s.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,s.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(u.nextDouble()n)return!1;B(),_.splice(n,1);var t=f(e.fromId),o=f(e.toId);return t&&(n=r(e,t.links),n>=0&&t.links.splice(n,1)),o&&(n=r(e,o.links),n>=0&&o.links.splice(n,1)),U(e,"remove"),F(),!0}function h(e,n){var t,r=f(e);if(!r)return null;for(t=0;tn;++n)e(_[n])}function x(e,n,t){var r=f(e);return r&&r.links&&"function"==typeof n?t?b(r.links,e,n):w(r.links,e,n):void 0}function w(e,n,t){for(var r,o=0;o0&&(O.fire("changed",M),M.length=0)}function N(){return Object.keys?k:A}function k(e){if("function"==typeof e)for(var n=Object.keys(j),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function o(e){this.id=e,this.links=[],this.data=null}function i(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=t;var a=e("ngraph.events")},{"ngraph.events":6}],25:[function(e,n){function t(e,n){var r;if(e||(e={}),n)for(r in n)if(n.hasOwnProperty(r)){var o=e.hasOwnProperty(r),i=typeof n[r],a=!o||typeof e[r]!==i;a?e[r]=n[r]:"object"===i&&(e[r]=t(e[r],n[r]))}return e}n.exports=t},{}],26:[function(e,n){function t(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function r(e,n){var r=n||t();if("function"!=typeof r.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var t,o,i;for(t=e.length-1;t>0;--t)o=r.next(t+1),i=e[o],e[o]=e[t],e[t]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,t,o;for(n=e.length-1;n>0;--n)t=r.next(n+1),o=e[t],e[t]=e[n],e[n]=o;return e}}}n.exports={random:t,randomIterator:r}},{}],27:[function(e,n){function t(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=t},{}],28:[function(e,n){function t(e,n){var t=r(e);if(void 0===n)return t;for(var o=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},A=function(e){p=!1,r.off("touchmove",k),r.off("touchend",A),r.off("touchcancel",A),c=null,a&&a(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,r.on("touchmove",k),r.on("touchend",A),r.on("touchcancel",A)) -},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return a=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),r.off("mousemove",w),r.off("mouseup",E),r.off("touchmove",k),r.off("touchend",A),r.off("touchcancel",A),P(null)}}}n.exports=t;var r=e("../Utils/documentEvents.js"),o=e("../Utils/browserInfo.js"),i=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":40,"../Utils/documentEvents.js":41,"../Utils/findElementPosition.js":42}],37:[function(e,n){function t(e,n){var t=r(n),o=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){o=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(o);var r=i[e.id];return r&&r.onStart&&r.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(o),o=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(o){var t=i[o.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=t;var r=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":58}],38:[function(e,n){function t(e,n){function t(e){return d[e]}n=r(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var a=o(n.seed),u=new i(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(){return{x:a.next(n.maxX),y:a.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"==typeof z?z:!0}function d(){G=G||window.document.body,F=F||o(e,o.simulator({springLength:80,springCoeff:2e-4})),O=O||i(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||u)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=s(function(){return p()},M)):(X=0,V=0,R=s(p,M)))}function g(){J||(W=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;en,t)}),e.forEachNode(E),T(),e.on("changed",j)}function D(){q=!1,T(),I(),a.off("resize",_),Q.off(),R.stop(),e.forEachLink(function(e){n.renderLinks&&b(e)}),e.forEachNode(function(e){L(e),x(e)}),F.dispose(),N()}var M=30;n=n||{};var U,R,B,F=n.layout,O=n.graphics,G=n.container,z=void 0!==n.interactive?n.interactive:!0,q=!1,Y=!0,X=0,V=0,W=!1,H=!1,J=!1,$={x:0,y:0},K={offsetX:0,offsetY:0,scale:1},Q=r({});return{run:function(e){return q||(d(),h(),m(),P(),S(),q=!0),v(e),this},reset:function(){O.resetScale(),m(),K.scale=1},pause:function(){J=!0,R.stop()},resume:function(){J=!1,R.restart()},rerender:function(){return l(),this},zoomOut:function(){return C(!0)},zoomIn:function(){return C(!1)},moveTo:function(e,n){O.graphCenterChanged(K.offsetX-e*K.scale,K.offsetY-n*K.scale),l()},getGraphics:function(){return O},dispose:function(){D()},on:function(e,n){return Q.on(e,n),this},off:function(e,n){return Q.off(e,n),this}}}n.exports=t;var r=e("ngraph.events"),o=e("ngraph.forcelayout"),i=e("./svgGraphics.js"),a=e("../Utils/windowEvents.js"),u=e("../Input/domInputManager.js"),s=e("../Utils/timer.js"),f=e("../Utils/getDimensions.js"),c=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.events":6,"ngraph.forcelayout":7}],50:[function(e,n){function t(){function e(){var e=r("svg");return n=r("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,a,u,s,f=1,c={},d={},l=function(){return r("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(){return r("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+a+","+u+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){a=e,u=n,w()},inputManager:i,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),s=n.getCTM().multiply(i);f=s.a,a=s.e,u=s.f;var c="matrix("+s.a+", 0, 0,"+s.d+","+s.e+","+s.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof s&&s(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):s=e),t},getSvgRoot:function(){return t}};return o(b),b}n.exports=t;var r=e("simplesvg"),o=e("ngraph.events"),i=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":35,"ngraph.events":6,simplesvg:28}],51:[function(e,n){function t(e){e=f(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,c,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=o(),P=i(),N=function(){return a()},k=function(){return u(3014898687)},A=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),c&&c.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(k=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:r,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,A()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],A()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,A(),I(this),y[0]},resetScale:function(){return j(),c&&(_(),A()),this},init:function(r){var o={};if(e.preserveDrawingBuffer&&(o.preserveDrawingBuffer=!0),n=r,_(),j(),n.appendChild(t),c=t.getContext("experimental-webgl",o),!c){var i="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(i),i}if(e.enableBlending&&(c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA),c.enable(c.BLEND)),e.clearColor){var a=e.clearColorValue;c.clearColor(a.r,a.g,a.b,a.a),this.beginRender=function(){c.clear(c.COLOR_BUFFER_BIT)}}L.load(c),L.updateSize(d/2,l/2),P.load(c),P.updateSize(d/2,l/2),A(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!c&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!c&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return s(T),T}n.exports=t;var r=e("../Input/webglInputManager.js"),o=e("../WebGL/webglLinkProgram.js"),i=e("../WebGL/webglNodeProgram.js"),a=e("../WebGL/webglSquare.js"),u=e("../WebGL/webglLine.js"),s=e("ngraph.events"),f=e("ngraph.merge")},{"../Input/webglInputManager.js":37,"../WebGL/webglLine.js":59,"../WebGL/webglLinkProgram.js":60,"../WebGL/webglNodeProgram.js":61,"../WebGL/webglSquare.js":62,"ngraph.events":6,"ngraph.merge":25}],52:[function(e,n){function t(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=t},{}],53:[function(e,n){function t(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=t},{}],54:[function(e,n){function t(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function i(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function o(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=t},{}],55:[function(e,n){function t(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!r(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:i,getCoordinates:a,load:u};return E}function r(e){return 0===(e&e-1)}var o=e("./texture.js");n.exports=t},{"./texture.js":53}],56:[function(e,n){function t(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=t},{}],57:[function(e,n){function t(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=r(),k=o(),A=1024,j=0,_=new Float32Array(64);return{load:t,position:u,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function r(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function o(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var i=e("./webglAtlas.js"),a=e("./webgl.js");n.exports=t},{"./webgl.js":54,"./webglAtlas.js":55}],58:[function(e,n){function t(e){function n(){x=null}function t(e){x=e}function o(e){return"function"==typeof e&&k.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(k,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],k=[],A=e.getGraphicsRoot();h(A);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:o,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var r=e("../Utils/documentEvents.js");n.exports=t},{"../Utils/documentEvents.js":41}],59:[function(e,n){function t(e){return{color:r(e)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],60:[function(e,n){function t(){var e,n,t,o,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,o=r(a),e=o.createProgram(v,p),n.useProgram(e),i=o.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&o.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&o.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],61:[function(e,n){function t(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=r(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function o(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(N,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:o,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],62:[function(e,n){function t(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],63:[function(e,n){n.exports="0.7.9"},{}]},{},[1])(1)}); \ No newline at end of file +},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return a=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),r.off("mousemove",w),r.off("mouseup",E),r.off("touchmove",k),r.off("touchend",A),r.off("touchcancel",A),P(null)}}}n.exports=t;var r=e("../Utils/documentEvents.js"),o=e("../Utils/browserInfo.js"),i=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":40,"../Utils/documentEvents.js":41,"../Utils/findElementPosition.js":42}],37:[function(e,n){function t(e,n){var t=r(n),o=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){o=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(o);var r=i[e.id];return r&&r.onStart&&r.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(o),o=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(o){var t=i[o.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=t;var r=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":58}],38:[function(e,n){function t(e,n){function t(e){return d[e]}n=r(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var a=o(n.seed),u=new i(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(){return{x:a.next(n.maxX),y:a.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"==typeof z?z:!0}function d(){G=G||window.document.body,F=F||o(e,o.simulator({springLength:80,springCoeff:2e-4})),O=O||i(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||u)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=s(function(){return p()},M)):(X=0,V=0,R=s(p,M)))}function g(){J||(W=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;en,t)}),e.forEachNode(E),T(),e.on("changed",j)}function D(){q=!1,T(),I(),a.off("resize",_),K.off(),R.stop(),e.forEachLink(function(e){n.renderLinks&&b(e)}),e.forEachNode(function(e){L(e),x(e)}),F.dispose(),N()}var M=30;n=n||{};var U,R,B,F=n.layout,O=n.graphics,G=n.container,z=void 0!==n.interactive?n.interactive:!0,q=!1,Y=!0,X=0,V=0,W=!1,H=!1,J=!1,$={offsetX:0,offsetY:0,scale:1},K=r({});return{run:function(e){return q||(d(),h(),P(),m(),S(),q=!0),v(e),this},reset:function(){O.resetScale(),m(),$.scale=1},pause:function(){J=!0,R.stop()},resume:function(){J=!1,R.restart()},rerender:function(){return l(),this},zoomOut:function(){return C(!0)},zoomIn:function(){return C(!1)},moveTo:function(e,n){O.graphCenterChanged($.offsetX-e*$.scale,$.offsetY-n*$.scale),l()},getGraphics:function(){return O},dispose:function(){D()},on:function(e,n){return K.on(e,n),this},off:function(e,n){return K.off(e,n),this}}}n.exports=t;var r=e("ngraph.events"),o=e("ngraph.forcelayout"),i=e("./svgGraphics.js"),a=e("../Utils/windowEvents.js"),u=e("../Input/domInputManager.js"),s=e("../Utils/timer.js"),f=e("../Utils/getDimensions.js"),c=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.events":6,"ngraph.forcelayout":7}],50:[function(e,n){function t(){function e(){var e=r("svg");return n=r("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,a,u=0,s=0,f=1,c={},d={},l=function(){return r("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(){return r("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+u+","+s+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){u=e,s=n,w()},inputManager:i,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),a=n.getCTM().multiply(i);f=a.a,u=a.e,s=a.f;var c="matrix("+a.a+", 0, 0,"+a.d+","+a.e+","+a.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof a&&a(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):a=e),t},getSvgRoot:function(){return t}};return o(b),b}n.exports=t;var r=e("simplesvg"),o=e("ngraph.events"),i=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":35,"ngraph.events":6,simplesvg:28}],51:[function(e,n){function t(e){e=f(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,c,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=o(),P=i(),N=function(){return a()},k=function(){return u(3014898687)},A=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),c&&c.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(k=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:r,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,A()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],A()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,A(),I(this),y[0]},resetScale:function(){return j(),c&&(_(),A()),this},init:function(r){var o={};if(e.preserveDrawingBuffer&&(o.preserveDrawingBuffer=!0),n=r,_(),j(),n.appendChild(t),c=t.getContext("experimental-webgl",o),!c){var i="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(i),i}if(e.enableBlending&&(c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA),c.enable(c.BLEND)),e.clearColor){var a=e.clearColorValue;c.clearColor(a.r,a.g,a.b,a.a),this.beginRender=function(){c.clear(c.COLOR_BUFFER_BIT)}}L.load(c),L.updateSize(d/2,l/2),P.load(c),P.updateSize(d/2,l/2),A(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!c&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!c&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return s(T),T}n.exports=t;var r=e("../Input/webglInputManager.js"),o=e("../WebGL/webglLinkProgram.js"),i=e("../WebGL/webglNodeProgram.js"),a=e("../WebGL/webglSquare.js"),u=e("../WebGL/webglLine.js"),s=e("ngraph.events"),f=e("ngraph.merge")},{"../Input/webglInputManager.js":37,"../WebGL/webglLine.js":59,"../WebGL/webglLinkProgram.js":60,"../WebGL/webglNodeProgram.js":61,"../WebGL/webglSquare.js":62,"ngraph.events":6,"ngraph.merge":25}],52:[function(e,n){function t(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=t},{}],53:[function(e,n){function t(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=t},{}],54:[function(e,n){function t(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function i(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function o(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=t},{}],55:[function(e,n){function t(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!r(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:i,getCoordinates:a,load:u};return E}function r(e){return 0===(e&e-1)}var o=e("./texture.js");n.exports=t},{"./texture.js":53}],56:[function(e,n){function t(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=t},{}],57:[function(e,n){function t(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=r(),k=o(),A=1024,j=0,_=new Float32Array(64);return{load:t,position:u,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function r(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function o(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var i=e("./webglAtlas.js"),a=e("./webgl.js");n.exports=t},{"./webgl.js":54,"./webglAtlas.js":55}],58:[function(e,n){function t(e){function n(){x=null}function t(e){x=e}function o(e){return"function"==typeof e&&k.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(k,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],k=[],A=e.getGraphicsRoot();h(A);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:o,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var r=e("../Utils/documentEvents.js");n.exports=t},{"../Utils/documentEvents.js":41}],59:[function(e,n){function t(e){return{color:r(e)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],60:[function(e,n){function t(){var e,n,t,o,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,o=r(a),e=o.createProgram(v,p),n.useProgram(e),i=o.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&o.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&o.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],61:[function(e,n){function t(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=r(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function o(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(N,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:o,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],62:[function(e,n){function t(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],63:[function(e,n){n.exports="0.7.10"},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/src/View/renderer.js b/src/View/renderer.js index 0a81f5f..c3fc3d9 100644 --- a/src/View/renderer.js +++ b/src/View/renderer.js @@ -262,8 +262,10 @@ function renderer(graph, settings) { var graphRect = layout.getGraphRect(), containerSize = getDimension(container); - transform.offsetX = containerSize.width / 2 - (graphRect.x2 + graphRect.x1) / 2; - transform.offsetY = containerSize.height / 2 - (graphRect.y2 + graphRect.y1) / 2; + var cx = (graphRect.x2 + graphRect.x1) / 2; + var cy = (graphRect.y2 + graphRect.y1) / 2; + transform.offsetX = containerSize.width / 2 - (cx * transform.scale - cx); + transform.offsetY = containerSize.height / 2 - (cy * transform.scale - cy); graphics.graphCenterChanged(transform.offsetX, transform.offsetY); updateCenterRequired = false; diff --git a/src/View/svgGraphics.js b/src/View/svgGraphics.js index 8024ec7..df7ad4d 100644 --- a/src/View/svgGraphics.js +++ b/src/View/svgGraphics.js @@ -17,8 +17,8 @@ var domInputManager = require('../Input/domInputManager.js'); function svgGraphics() { var svgContainer, svgRoot, - offsetX, - offsetY, + offsetX = 0, + offsetY = 0, initCallback, actualScale = 1, allNodes = {}, diff --git a/src/version.js b/src/version.js index 8c50d1e..317c93d 100644 --- a/src/version.js +++ b/src/version.js @@ -1,2 +1,2 @@ // todo: this should be generated at build time. -module.exports = '0.7.9'; +module.exports = '0.7.10'; From 54c284ecbe6466e8c5e2b69d74c3359389164b65 Mon Sep 17 00:00:00 2001 From: anvaka Date: Mon, 13 Apr 2015 18:50:05 -0700 Subject: [PATCH 198/276] 0.7.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 54d108b..fa28fed 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.7.9", + "version": "0.7.10", "description": "Graph Drawing Library", "main": "src/viva", "directories": { From cab1fca26d74713f8b556891f615e08b766c60cb Mon Sep 17 00:00:00 2001 From: anvaka Date: Thu, 16 Apr 2015 18:23:06 -0700 Subject: [PATCH 199/276] Unified force layout api accross ngraph modules Now force layout accepts simulator settings, instead of simulator itself. This does not affect external API of VivaGraph, yet provides consistency for ngraph modules --- dist/vivagraph.js | 165 +++++++++++++++--------------------------- dist/vivagraph.min.js | 4 +- package.json | 2 +- src/View/renderer.js | 4 +- src/version.js | 2 +- src/viva.js | 6 +- 6 files changed, 65 insertions(+), 118 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 4002285..8142578 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -62,11 +62,7 @@ Viva.Graph = { }, Layout: { - forceDirected: function(graph, physicsSettings) { - // vivagraph had slightly different API: - var forceLayout = require('ngraph.forcelayout'); - return forceLayout(graph, forceLayout.simulator(physicsSettings)); - }, + forceDirected: require('ngraph.forcelayout'), constant: require('./Layout/constant.js') }, @@ -116,7 +112,7 @@ Viva.Graph = { module.exports = Viva; -},{"./Algorithms/centrality.js":33,"./Algorithms/operations.js":34,"./Input/domInputManager.js":35,"./Input/dragndrop.js":36,"./Input/webglInputManager.js":37,"./Layout/constant.js":38,"./Utils/backwardCompatibleEvents.js":39,"./Utils/browserInfo.js":40,"./Utils/findElementPosition.js":42,"./Utils/getDimensions.js":43,"./Utils/intersectRect.js":44,"./Utils/rect.js":46,"./Utils/timer.js":47,"./View/renderer.js":49,"./View/svgGraphics.js":50,"./View/webglGraphics.js":51,"./WebGL/parseColor.js":52,"./WebGL/texture.js":53,"./WebGL/webgl.js":54,"./WebGL/webglAtlas.js":55,"./WebGL/webglImage.js":56,"./WebGL/webglImageNodeProgram.js":57,"./WebGL/webglInputEvents.js":58,"./WebGL/webglLine.js":59,"./WebGL/webglLinkProgram.js":60,"./WebGL/webglNodeProgram.js":61,"./WebGL/webglSquare.js":62,"./version.js":63,"gintersect":2,"ngraph.events":6,"ngraph.forcelayout":7,"ngraph.fromjson":22,"ngraph.generators":23,"ngraph.graph":24,"ngraph.merge":25,"ngraph.random":26,"ngraph.tojson":27,"simplesvg":28}],2:[function(require,module,exports){ +},{"./Algorithms/centrality.js":32,"./Algorithms/operations.js":33,"./Input/domInputManager.js":34,"./Input/dragndrop.js":35,"./Input/webglInputManager.js":36,"./Layout/constant.js":37,"./Utils/backwardCompatibleEvents.js":38,"./Utils/browserInfo.js":39,"./Utils/findElementPosition.js":41,"./Utils/getDimensions.js":42,"./Utils/intersectRect.js":43,"./Utils/rect.js":45,"./Utils/timer.js":46,"./View/renderer.js":48,"./View/svgGraphics.js":49,"./View/webglGraphics.js":50,"./WebGL/parseColor.js":51,"./WebGL/texture.js":52,"./WebGL/webgl.js":53,"./WebGL/webglAtlas.js":54,"./WebGL/webglImage.js":55,"./WebGL/webglImageNodeProgram.js":56,"./WebGL/webglInputEvents.js":57,"./WebGL/webglLine.js":58,"./WebGL/webglLinkProgram.js":59,"./WebGL/webglNodeProgram.js":60,"./WebGL/webglSquare.js":61,"./version.js":62,"gintersect":2,"ngraph.events":6,"ngraph.forcelayout":7,"ngraph.fromjson":21,"ngraph.generators":22,"ngraph.graph":23,"ngraph.merge":24,"ngraph.random":25,"ngraph.tojson":26,"simplesvg":27}],2:[function(require,module,exports){ module.exports = intersect; /** @@ -488,25 +484,20 @@ function validateSubject(subject) { module.exports = createLayout; module.exports.simulator = require('ngraph.physics.simulator'); -var guard = require('varta'); - /** * Creates force based layout for a given graph. * @param {ngraph.graph} graph which needs to be laid out - * @param {ngraph.physics.simulator=} physicsSimulator if you need custom settings - * for physics simulator you can pass your own simulator here. If it's not passed - * a default one will be created + * @param {object} physicsSettings if you need custom settings + * for physics simulator you can pass your own settings here. If it's not passed + * a default one will be created. */ -function createLayout(graph, physicsSimulator) { +function createLayout(graph, physicsSettings) { if (!graph) { throw new Error('Graph structure cannot be undefined'); } - var simulator = require('ngraph.physics.simulator'); - - physicsSimulator = physicsSimulator || simulator(); - - guard(physicsSimulator, 'physicsSimulator').has('step', 'getBestNewBodyPosition', 'addBodyAt'); + var createSimulator = require('ngraph.physics.simulator'); + var physicsSimulator = createSimulator(physicsSettings); var nodeBodies = typeof Object.create === 'function' ? Object.create(null) : {}; var springs = {}; @@ -793,7 +784,7 @@ function createLayout(graph, physicsSimulator) { function noop() { } -},{"ngraph.physics.simulator":8,"varta":21}],8:[function(require,module,exports){ +},{"ngraph.physics.simulator":8}],8:[function(require,module,exports){ /** * Manages a simulation of physical forces acting on bodies and springs. */ @@ -1049,7 +1040,7 @@ function physicsSimulator(settings) { } }; -},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":25,"ngraph.quadtreebh":17}],9:[function(require,module,exports){ +},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":24,"ngraph.quadtreebh":17}],9:[function(require,module,exports){ module.exports = function (bodies, settings) { var random = require('ngraph.random').random(42); var boundingBox = { x1: 0, y1: 0, x2: 0, y2: 0 }; @@ -1131,7 +1122,7 @@ module.exports = function (bodies, settings) { } } -},{"ngraph.random":26}],10:[function(require,module,exports){ +},{"ngraph.random":25}],10:[function(require,module,exports){ var physics = require('ngraph.physics.primitives'); module.exports = function(pos) { @@ -1167,7 +1158,7 @@ module.exports = function (options) { return api; }; -},{"ngraph.expose":15,"ngraph.merge":25}],12:[function(require,module,exports){ +},{"ngraph.expose":15,"ngraph.merge":24}],12:[function(require,module,exports){ /** * Performs forces integration, using given timestep. Uses Euler method to solve * differential equation (http://en.wikipedia.org/wiki/Euler_method ). @@ -1278,7 +1269,7 @@ module.exports = function (options) { return api; } -},{"ngraph.expose":15,"ngraph.merge":25,"ngraph.random":26}],15:[function(require,module,exports){ +},{"ngraph.expose":15,"ngraph.merge":24,"ngraph.random":25}],15:[function(require,module,exports){ module.exports = exposeProperties; /** @@ -1717,7 +1708,7 @@ function setChild(node, idx, child) { else if (idx === 3) node.quad3 = child; } -},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":26}],18:[function(require,module,exports){ +},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":25}],18:[function(require,module,exports){ module.exports = InsertStack; /** @@ -1802,46 +1793,6 @@ module.exports = function Node() { }; },{}],21:[function(require,module,exports){ -module.exports = varta; - -module.exports.has = delayedVerify; - -function varta(suspect, name) { - name = name || 'Argument'; - - return { - has: has - }; - - function has() { - return internalVerify(suspect, name, arguments); - } -} - -function delayedVerify() { - var expectations = arguments; - return verify; - - function verify(suspect, name) { - return internalVerify(suspect, name, expectations); - } -} - -function internalVerify(suspect, name, expectations) { - if (suspect === undefined) { - throw new Error(name + ' is not defined'); - } - - for (var i = 0; i < expectations.length; ++i) { - if (suspect[expectations[i]] === undefined) { - throw new Error(name + ' is expected to have a property `' + expectations[i] + '`'); - } - } - - return true; -} - -},{}],22:[function(require,module,exports){ module.exports = load; var createGraph = require('ngraph.graph'); @@ -1886,7 +1837,7 @@ function load(jsonGraph, nodeTransform, linkTransform) { function id(x) { return x; } -},{"ngraph.graph":24}],23:[function(require,module,exports){ +},{"ngraph.graph":23}],22:[function(require,module,exports){ module.exports = { ladder: ladder, complete: complete, @@ -2187,7 +2138,7 @@ function wattsStrogatz(n, k, p, seed) { return g; } -},{"ngraph.graph":24,"ngraph.random":26}],24:[function(require,module,exports){ +},{"ngraph.graph":23,"ngraph.random":25}],23:[function(require,module,exports){ /** * @fileOverview Contains definition of the core graph object. */ @@ -2741,7 +2692,7 @@ function Link(fromId, toId, data, id) { this.id = id; } -},{"ngraph.events":6}],25:[function(require,module,exports){ +},{"ngraph.events":6}],24:[function(require,module,exports){ module.exports = merge; /** @@ -2774,7 +2725,7 @@ function merge(target, options) { return target; } -},{}],26:[function(require,module,exports){ +},{}],25:[function(require,module,exports){ module.exports = { random: random, randomIterator: randomIterator @@ -2861,7 +2812,7 @@ function randomIterator(array, customRandom) { }; } -},{}],27:[function(require,module,exports){ +},{}],26:[function(require,module,exports){ module.exports = save; function save(graph, customNodeTransform, customLinkTransform) { @@ -2917,7 +2868,7 @@ function save(graph, customNodeTransform, customLinkTransform) { } } -},{}],28:[function(require,module,exports){ +},{}],27:[function(require,module,exports){ module.exports = svg; svg.compile = require('./lib/compile'); @@ -3030,7 +2981,7 @@ function augment(element) { } } -},{"./lib/compile":29,"./lib/compile_template":30,"add-event-listener":32}],29:[function(require,module,exports){ +},{"./lib/compile":28,"./lib/compile_template":29,"add-event-listener":31}],28:[function(require,module,exports){ var parser = require('./domparser.js'); var svg = require('../'); @@ -3058,7 +3009,7 @@ function addNamespaces(text) { } } -},{"../":28,"./domparser.js":31}],30:[function(require,module,exports){ +},{"../":27,"./domparser.js":30}],29:[function(require,module,exports){ module.exports = template; var BINDING_EXPR = /{{(.+?)}}/; @@ -3152,7 +3103,7 @@ function bindTextContent(element, allBindings) { } } -},{}],31:[function(require,module,exports){ +},{}],30:[function(require,module,exports){ module.exports = createDomparser(); function createDomparser() { @@ -3168,7 +3119,7 @@ function fail() { throw new Error('DOMParser is not supported by this platform. Please open issue here https://github.com/anvaka/simplesvg'); } -},{}],32:[function(require,module,exports){ +},{}],31:[function(require,module,exports){ addEventListener.removeEventListener = removeEventListener addEventListener.addEventListener = addEventListener @@ -3216,7 +3167,7 @@ function oldIEDetach(el, eventName, listener, useCapture) { el.detachEvent('on' + eventName, listener) } -},{}],33:[function(require,module,exports){ +},{}],32:[function(require,module,exports){ var centrality = require('ngraph.centrality'); module.exports = centralityWrapper; @@ -3254,7 +3205,7 @@ function toVivaGraphCentralityFormat(centrality) { } } -},{"ngraph.centrality":3}],34:[function(require,module,exports){ +},{"ngraph.centrality":3}],33:[function(require,module,exports){ /** * @fileOverview Contains collection of primitive operations under graph. * @@ -3289,7 +3240,7 @@ function operations() { }; }; -},{}],35:[function(require,module,exports){ +},{}],34:[function(require,module,exports){ /** * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ @@ -3338,7 +3289,7 @@ function domInputManager(graph, graphics) { } } -},{"./dragndrop.js":36}],36:[function(require,module,exports){ +},{"./dragndrop.js":35}],35:[function(require,module,exports){ /** * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ @@ -3621,7 +3572,7 @@ function dragndrop(element) { }; } -},{"../Utils/browserInfo.js":40,"../Utils/documentEvents.js":41,"../Utils/findElementPosition.js":42}],37:[function(require,module,exports){ +},{"../Utils/browserInfo.js":39,"../Utils/documentEvents.js":40,"../Utils/findElementPosition.js":41}],36:[function(require,module,exports){ /** * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ @@ -3692,7 +3643,7 @@ function webglInputManager(graph, graphics) { }; } -},{"../WebGL/webglInputEvents.js":58}],38:[function(require,module,exports){ +},{"../WebGL/webglInputEvents.js":57}],37:[function(require,module,exports){ module.exports = constant; var merge = require('ngraph.merge'); @@ -3891,7 +3842,7 @@ function constant(graph, userSettings) { } } -},{"../Utils/rect.js":46,"ngraph.merge":25,"ngraph.random":26}],39:[function(require,module,exports){ +},{"../Utils/rect.js":45,"ngraph.merge":24,"ngraph.random":25}],38:[function(require,module,exports){ /** * This module provides compatibility layer with 0.6.x library. It will be * removed in the next version @@ -3936,7 +3887,7 @@ function backwardCompatibleEvents(g) { } } -},{"ngraph.events":6}],40:[function(require,module,exports){ +},{"ngraph.events":6}],39:[function(require,module,exports){ module.exports = browserInfo(); function browserInfo() { @@ -3965,7 +3916,7 @@ function browserInfo() { }; } -},{}],41:[function(require,module,exports){ +},{}],40:[function(require,module,exports){ var nullEvents = require('./nullEvents.js'); module.exports = createDocumentEvents(); @@ -3989,7 +3940,7 @@ function off(eventName, handler) { document.removeEventListener(eventName, handler); } -},{"./nullEvents.js":45}],42:[function(require,module,exports){ +},{"./nullEvents.js":44}],41:[function(require,module,exports){ /** * Finds the absolute position of an element on a page */ @@ -4008,7 +3959,7 @@ function findElementPosition(obj) { return [curleft, curtop]; } -},{}],43:[function(require,module,exports){ +},{}],42:[function(require,module,exports){ module.exports = getDimension; function getDimension(container) { @@ -4030,7 +3981,7 @@ function getDimension(container) { }; } -},{}],44:[function(require,module,exports){ +},{}],43:[function(require,module,exports){ var intersect = require('gintersect'); module.exports = intersectRect; @@ -4042,7 +3993,7 @@ function intersectRect(left, top, right, bottom, x1, y1, x2, y2) { intersect(right, top, left, top, x1, y1, x2, y2); } -},{"gintersect":2}],45:[function(require,module,exports){ +},{"gintersect":2}],44:[function(require,module,exports){ module.exports = createNullEvents(); function createNullEvents() { @@ -4055,7 +4006,7 @@ function createNullEvents() { function noop() { } -},{}],46:[function(require,module,exports){ +},{}],45:[function(require,module,exports){ module.exports = Rect; /** @@ -4068,7 +4019,7 @@ function Rect (x1, y1, x2, y2) { this.y2 = y2 || 0; } -},{}],47:[function(require,module,exports){ +},{}],46:[function(require,module,exports){ (function (global){ /** * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com @@ -4164,7 +4115,7 @@ function createTimer() { function noop() {} }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],48:[function(require,module,exports){ +},{}],47:[function(require,module,exports){ var nullEvents = require('./nullEvents.js'); module.exports = createDocumentEvents(); @@ -4189,7 +4140,7 @@ function off(eventName, handler) { } -},{"./nullEvents.js":45}],49:[function(require,module,exports){ +},{"./nullEvents.js":44}],48:[function(require,module,exports){ /** * @fileOverview Defines a graph renderer that uses CSS based drawings. * @@ -4378,10 +4329,10 @@ function renderer(graph, settings) { function prepareSettings() { container = container || window.document.body; - layout = layout || forceDirected(graph, forceDirected.simulator({ + layout = layout || forceDirected(graph, { springLength: 80, springCoeff: 0.0002, - })); + }); graphics = graphics || svgGraphics(graph, { container: container }); @@ -4666,7 +4617,7 @@ function renderer(graph, settings) { } } -},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.events":6,"ngraph.forcelayout":7}],50:[function(require,module,exports){ +},{"../Input/domInputManager.js":34,"../Input/dragndrop.js":35,"../Utils/getDimensions.js":42,"../Utils/timer.js":46,"../Utils/windowEvents.js":47,"./svgGraphics.js":49,"ngraph.events":6,"ngraph.forcelayout":7}],49:[function(require,module,exports){ /** * @fileOverview Defines a graph renderer that uses SVG based drawings. * @@ -5024,7 +4975,7 @@ function svgGraphics() { } } -},{"../Input/domInputManager.js":35,"ngraph.events":6,"simplesvg":28}],51:[function(require,module,exports){ +},{"../Input/domInputManager.js":34,"ngraph.events":6,"simplesvg":27}],50:[function(require,module,exports){ /** * @fileOverview Defines a graph renderer that uses WebGL based drawings. * @@ -5572,7 +5523,7 @@ function webglGraphics(options) { return graphics; } -},{"../Input/webglInputManager.js":37,"../WebGL/webglLine.js":59,"../WebGL/webglLinkProgram.js":60,"../WebGL/webglNodeProgram.js":61,"../WebGL/webglSquare.js":62,"ngraph.events":6,"ngraph.merge":25}],52:[function(require,module,exports){ +},{"../Input/webglInputManager.js":36,"../WebGL/webglLine.js":58,"../WebGL/webglLinkProgram.js":59,"../WebGL/webglNodeProgram.js":60,"../WebGL/webglSquare.js":61,"ngraph.events":6,"ngraph.merge":24}],51:[function(require,module,exports){ module.exports = parseColor; function parseColor(color) { @@ -5596,7 +5547,7 @@ function parseColor(color) { return parsedColor; } -},{}],53:[function(require,module,exports){ +},{}],52:[function(require,module,exports){ module.exports = Texture; /** @@ -5609,7 +5560,7 @@ function Texture(size) { this.canvas.width = this.canvas.height = size; } -},{}],54:[function(require,module,exports){ +},{}],53:[function(require,module,exports){ /** * @fileOverview Utility functions for webgl rendering. * @@ -5716,7 +5667,7 @@ function swapArrayPart(array, from, to, elementsCount) { } } -},{}],55:[function(require,module,exports){ +},{}],54:[function(require,module,exports){ var Texture = require('./texture.js'); module.exports = webglAtlas; @@ -5920,7 +5871,7 @@ function isPowerOf2(n) { return (n & (n - 1)) === 0; } -},{"./texture.js":53}],56:[function(require,module,exports){ +},{"./texture.js":52}],55:[function(require,module,exports){ module.exports = webglImage; /** @@ -5952,7 +5903,7 @@ function webglImage(size, src) { }; } -},{}],57:[function(require,module,exports){ +},{}],56:[function(require,module,exports){ /** * @fileOverview Defines an image nodes for webglGraphics class. * Shape of nodes is square. @@ -6216,7 +6167,7 @@ function createNodeVertexShader() { ].join("\n"); } -},{"./webgl.js":54,"./webglAtlas.js":55}],58:[function(require,module,exports){ +},{"./webgl.js":53,"./webglAtlas.js":54}],57:[function(require,module,exports){ var documentEvents = require('../Utils/documentEvents.js'); module.exports = webglInputEvents; @@ -6474,7 +6425,7 @@ function webglInputEvents(webglGraphics) { } } -},{"../Utils/documentEvents.js":41}],59:[function(require,module,exports){ +},{"../Utils/documentEvents.js":40}],58:[function(require,module,exports){ var parseColor = require('./parseColor.js'); module.exports = webglLine; @@ -6495,7 +6446,7 @@ function webglLine(color) { }; } -},{"./parseColor.js":52}],60:[function(require,module,exports){ +},{"./parseColor.js":51}],59:[function(require,module,exports){ /** * @fileOverview Defines a naive form of links for webglGraphics class. * This form allows to change color of links. @@ -6653,7 +6604,7 @@ function webglLinkProgram() { }; } -},{"./webgl.js":54}],61:[function(require,module,exports){ +},{"./webgl.js":53}],60:[function(require,module,exports){ /** * @fileOverview Defines a naive form of nodes for webglGraphics class. * This form allows to change color of node. Shape of nodes is rectangular. @@ -6818,7 +6769,7 @@ function webglNodeProgram() { } } -},{"./webgl.js":54}],62:[function(require,module,exports){ +},{"./webgl.js":53}],61:[function(require,module,exports){ var parseColor = require('./parseColor.js'); module.exports = webglSquare; @@ -6844,9 +6795,9 @@ function webglSquare(size, color) { }; } -},{"./parseColor.js":52}],63:[function(require,module,exports){ +},{"./parseColor.js":51}],62:[function(require,module,exports){ // todo: this should be generated at build time. -module.exports = '0.7.10'; +module.exports = '0.7.11'; },{}]},{},[1])(1) }); \ No newline at end of file diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 7a99901..a4ed601 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-s*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=t},{}],3:[function(e,n){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n){function t(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function g(e){var n=w[e];n.mass=y(e)}function h(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function m(e){var n=w[e];return n||(c(e),n=w[e]),n}function y(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var x=e("ngraph.physics.simulator");t=t||x(),o(t,"physicsSimulator").has("step","getBestNewBodyPosition","addBodyAt");var w="function"==typeof Object.create?Object.create(null):{},b={},E=t.settings.springTransform||r;f(),u();var L={step:function(){return t.step()},getNodePosition:function(e){return m(e).pos},setNodePosition:function(e){var n=m(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return t.getBBox()},pinNode:function(e,n){var t=m(e.id);t.isPinned=!!n},isNodePinned:function(e){return m(e.id).isPinned},dispose:function(){n.off("changed",s)},getBody:a,getSpring:i,simulator:t};return L}function r(){}n.exports=t,n.exports.simulator=e("ngraph.physics.simulator");var o=e("varta")},{"ngraph.physics.simulator":8,varta:21}],8:[function(e,n){function t(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.force.reset(),v.updateBodyForce(e),m.update(e);for(n=p.length;n--;)h.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),u=n.createBounds||e("./lib/bounds"),s=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),g=u(l,n),h=f(n),m=s(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return g.update(),en))return l.splice(n,1),0===l.length&&g.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return g.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=t},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":25,"ngraph.quadtreebh":17}],9:[function(e,n){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;ut;++t){var s=e[t],f=n/s.mass;s.velocity.x+=f*s.force.x,s.velocity.y+=f*s.force.y;var c=s.velocity.x,d=s.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=t},{}],13:[function(e,n){function t(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=t},{}],14:[function(e,n){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":25,"ngraph.random":26}],15:[function(e,n){function t(e,n,t){var o="[object Array]"===Object.prototype.toString.call(t);if(o)for(var i=0;i0&&u(s.pos,a.pos));if(0===f&&u(s.pos,a.pos))return}c.push(i,s),c.push(i,a)}else{var h=a.pos.x,m=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*h,i.massY=i.massY+a.mass*m;var y=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;if(h>w){y+=1;var L=x;x=w,w+=w-L}if(m>E){y+=2;var P=b;b=E,E+=E-P}var N=t(i,y);N?c.push(N,a):(N=v(),N.left=x,N.top=b,N.right=w,N.bottom=E,N.body=a,r(i,y,N))}}},m=function(e){var n,t,r,i,a=f,u=0,c=0,l=1,p=0,v=1;for(a[0]=g;l;){var h=a[p],m=h.body;l-=1,p+=1;var y=m!==e;m&&y?(t=m.pos.x-e.pos.x,r=m.pos.y-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),n=s*m.mass*e.mass/(i*i*i),u+=n*t,c+=n*r):y&&(t=h.massX/h.mass-e.pos.x,r=h.massY/h.mass-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),(h.right-h.left)/iu&&(t=u),u>o&&(o=u),r>s&&(r=s),s>i&&(i=s)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,p=0,g=v(),g.left=t,g.right=o,g.top=r,g.bottom=i,n=a-1,n>0&&(g.body=e[n]);n--;)h(e[n],g)};return{insertBodies:y,updateBodyForce:m,options:function(e){return e?("number"==typeof e.gravity&&(s=e.gravity),"number"==typeof e.theta&&(d=e.theta),this):{gravity:s,theta:d}}}}},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":26}],18:[function(e,n){function t(){this.stack=[],this.popIdx=0}function r(e,n){this.node=e,this.body=n}n.exports=t,t.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new r(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],19:[function(e,n){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],20:[function(e,n){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],21:[function(e,n){function t(e,n){function t(){return o(e,n,arguments)}return n=n||"Argument",{has:t}}function r(){function e(e,t){return o(e,t,n)}var n=arguments;return e}function o(e,n,t){if(void 0===e)throw new Error(n+" is not defined");for(var r=0;re)throw new Error("Invalid number of nodes");var n,t=l();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function r(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=t(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function o(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=l();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function i(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=l();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function a(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=l();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function u(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=l();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function s(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=l();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var u=i*e*n,s=r+o*e+u;r>0&&a.addLink(s,r-1+o*e+u),o>0&&a.addLink(s,r+(o-1)*e+u),i>0&&a.addLink(s,r+o*e+(i-1)*e*n)}return a}function f(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=l(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function c(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=l();for(n=0;e>n;++n)t.addNode(n);return t}function d(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,u=e("ngraph.random").random(o||42),s=l();for(i=0;n>i;++i)s.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,s.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(u.nextDouble()n)return!1;B(),_.splice(n,1);var t=f(e.fromId),o=f(e.toId);return t&&(n=r(e,t.links),n>=0&&t.links.splice(n,1)),o&&(n=r(e,o.links),n>=0&&o.links.splice(n,1)),U(e,"remove"),F(),!0}function h(e,n){var t,r=f(e);if(!r)return null;for(t=0;tn;++n)e(_[n])}function x(e,n,t){var r=f(e);return r&&r.links&&"function"==typeof n?t?b(r.links,e,n):w(r.links,e,n):void 0}function w(e,n,t){for(var r,o=0;o0&&(O.fire("changed",M),M.length=0)}function N(){return Object.keys?k:A}function k(e){if("function"==typeof e)for(var n=Object.keys(j),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function o(e){this.id=e,this.links=[],this.data=null}function i(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=t;var a=e("ngraph.events")},{"ngraph.events":6}],25:[function(e,n){function t(e,n){var r;if(e||(e={}),n)for(r in n)if(n.hasOwnProperty(r)){var o=e.hasOwnProperty(r),i=typeof n[r],a=!o||typeof e[r]!==i;a?e[r]=n[r]:"object"===i&&(e[r]=t(e[r],n[r]))}return e}n.exports=t},{}],26:[function(e,n){function t(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function r(e,n){var r=n||t();if("function"!=typeof r.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var t,o,i;for(t=e.length-1;t>0;--t)o=r.next(t+1),i=e[o],e[o]=e[t],e[t]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,t,o;for(n=e.length-1;n>0;--n)t=r.next(n+1),o=e[t],e[t]=e[n],e[n]=o;return e}}}n.exports={random:t,randomIterator:r}},{}],27:[function(e,n){function t(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=t},{}],28:[function(e,n){function t(e,n){var t=r(e);if(void 0===n)return t;for(var o=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},A=function(e){p=!1,r.off("touchmove",k),r.off("touchend",A),r.off("touchcancel",A),c=null,a&&a(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,r.on("touchmove",k),r.on("touchend",A),r.on("touchcancel",A)) -},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return a=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),r.off("mousemove",w),r.off("mouseup",E),r.off("touchmove",k),r.off("touchend",A),r.off("touchcancel",A),P(null)}}}n.exports=t;var r=e("../Utils/documentEvents.js"),o=e("../Utils/browserInfo.js"),i=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":40,"../Utils/documentEvents.js":41,"../Utils/findElementPosition.js":42}],37:[function(e,n){function t(e,n){var t=r(n),o=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){o=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(o);var r=i[e.id];return r&&r.onStart&&r.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(o),o=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(o){var t=i[o.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=t;var r=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":58}],38:[function(e,n){function t(e,n){function t(e){return d[e]}n=r(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var a=o(n.seed),u=new i(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(){return{x:a.next(n.maxX),y:a.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"==typeof z?z:!0}function d(){G=G||window.document.body,F=F||o(e,o.simulator({springLength:80,springCoeff:2e-4})),O=O||i(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||u)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=s(function(){return p()},M)):(X=0,V=0,R=s(p,M)))}function g(){J||(W=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;en,t)}),e.forEachNode(E),T(),e.on("changed",j)}function D(){q=!1,T(),I(),a.off("resize",_),K.off(),R.stop(),e.forEachLink(function(e){n.renderLinks&&b(e)}),e.forEachNode(function(e){L(e),x(e)}),F.dispose(),N()}var M=30;n=n||{};var U,R,B,F=n.layout,O=n.graphics,G=n.container,z=void 0!==n.interactive?n.interactive:!0,q=!1,Y=!0,X=0,V=0,W=!1,H=!1,J=!1,$={offsetX:0,offsetY:0,scale:1},K=r({});return{run:function(e){return q||(d(),h(),P(),m(),S(),q=!0),v(e),this},reset:function(){O.resetScale(),m(),$.scale=1},pause:function(){J=!0,R.stop()},resume:function(){J=!1,R.restart()},rerender:function(){return l(),this},zoomOut:function(){return C(!0)},zoomIn:function(){return C(!1)},moveTo:function(e,n){O.graphCenterChanged($.offsetX-e*$.scale,$.offsetY-n*$.scale),l()},getGraphics:function(){return O},dispose:function(){D()},on:function(e,n){return K.on(e,n),this},off:function(e,n){return K.off(e,n),this}}}n.exports=t;var r=e("ngraph.events"),o=e("ngraph.forcelayout"),i=e("./svgGraphics.js"),a=e("../Utils/windowEvents.js"),u=e("../Input/domInputManager.js"),s=e("../Utils/timer.js"),f=e("../Utils/getDimensions.js"),c=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":35,"../Input/dragndrop.js":36,"../Utils/getDimensions.js":43,"../Utils/timer.js":47,"../Utils/windowEvents.js":48,"./svgGraphics.js":50,"ngraph.events":6,"ngraph.forcelayout":7}],50:[function(e,n){function t(){function e(){var e=r("svg");return n=r("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,a,u=0,s=0,f=1,c={},d={},l=function(){return r("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(){return r("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+u+","+s+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){u=e,s=n,w()},inputManager:i,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),a=n.getCTM().multiply(i);f=a.a,u=a.e,s=a.f;var c="matrix("+a.a+", 0, 0,"+a.d+","+a.e+","+a.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof a&&a(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):a=e),t},getSvgRoot:function(){return t}};return o(b),b}n.exports=t;var r=e("simplesvg"),o=e("ngraph.events"),i=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":35,"ngraph.events":6,simplesvg:28}],51:[function(e,n){function t(e){e=f(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,c,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=o(),P=i(),N=function(){return a()},k=function(){return u(3014898687)},A=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),c&&c.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(k=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:r,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,A()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],A()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,A(),I(this),y[0]},resetScale:function(){return j(),c&&(_(),A()),this},init:function(r){var o={};if(e.preserveDrawingBuffer&&(o.preserveDrawingBuffer=!0),n=r,_(),j(),n.appendChild(t),c=t.getContext("experimental-webgl",o),!c){var i="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(i),i}if(e.enableBlending&&(c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA),c.enable(c.BLEND)),e.clearColor){var a=e.clearColorValue;c.clearColor(a.r,a.g,a.b,a.a),this.beginRender=function(){c.clear(c.COLOR_BUFFER_BIT)}}L.load(c),L.updateSize(d/2,l/2),P.load(c),P.updateSize(d/2,l/2),A(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!c&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!c&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return s(T),T}n.exports=t;var r=e("../Input/webglInputManager.js"),o=e("../WebGL/webglLinkProgram.js"),i=e("../WebGL/webglNodeProgram.js"),a=e("../WebGL/webglSquare.js"),u=e("../WebGL/webglLine.js"),s=e("ngraph.events"),f=e("ngraph.merge")},{"../Input/webglInputManager.js":37,"../WebGL/webglLine.js":59,"../WebGL/webglLinkProgram.js":60,"../WebGL/webglNodeProgram.js":61,"../WebGL/webglSquare.js":62,"ngraph.events":6,"ngraph.merge":25}],52:[function(e,n){function t(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=t},{}],53:[function(e,n){function t(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=t},{}],54:[function(e,n){function t(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function i(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function o(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=t},{}],55:[function(e,n){function t(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!r(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:i,getCoordinates:a,load:u};return E}function r(e){return 0===(e&e-1)}var o=e("./texture.js");n.exports=t},{"./texture.js":53}],56:[function(e,n){function t(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=t},{}],57:[function(e,n){function t(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=r(),k=o(),A=1024,j=0,_=new Float32Array(64);return{load:t,position:u,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function r(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function o(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var i=e("./webglAtlas.js"),a=e("./webgl.js");n.exports=t},{"./webgl.js":54,"./webglAtlas.js":55}],58:[function(e,n){function t(e){function n(){x=null}function t(e){x=e}function o(e){return"function"==typeof e&&k.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(k,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],k=[],A=e.getGraphicsRoot();h(A);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:o,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var r=e("../Utils/documentEvents.js");n.exports=t},{"../Utils/documentEvents.js":41}],59:[function(e,n){function t(e){return{color:r(e)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],60:[function(e,n){function t(){var e,n,t,o,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,o=r(a),e=o.createProgram(v,p),n.useProgram(e),i=o.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&o.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&o.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],61:[function(e,n){function t(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=r(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function o(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(N,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:o,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":54}],62:[function(e,n){function t(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":52}],63:[function(e,n){n.exports="0.7.10"},{}]},{},[1])(1)}); \ No newline at end of file +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-s*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=t},{}],3:[function(e,n){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n){function t(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function v(e){var n=w[e];n.mass=m(e)}function g(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function h(e){var n=w[e];return n||(f(e),n=w[e]),n}function m(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var y=e("ngraph.physics.simulator"),x=y(t),w="function"==typeof Object.create?Object.create(null):{},b={},E=x.settings.springTransform||r;s(),a();var L={step:function(){return x.step()},getNodePosition:function(e){return h(e).pos},setNodePosition:function(e){var n=h(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return x.getBBox()},pinNode:function(e,n){var t=h(e.id);t.isPinned=!!n},isNodePinned:function(e){return h(e.id).isPinned},dispose:function(){n.off("changed",u)},getBody:i,getSpring:o,simulator:x};return L}function r(){}n.exports=t,n.exports.simulator=e("ngraph.physics.simulator")},{"ngraph.physics.simulator":8}],8:[function(e,n){function t(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.force.reset(),v.updateBodyForce(e),m.update(e);for(n=p.length;n--;)h.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),u=n.createBounds||e("./lib/bounds"),s=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),g=u(l,n),h=f(n),m=s(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return g.update(),en))return l.splice(n,1),0===l.length&&g.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return g.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=t},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":24,"ngraph.quadtreebh":17}],9:[function(e,n){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;ut;++t){var s=e[t],f=n/s.mass;s.velocity.x+=f*s.force.x,s.velocity.y+=f*s.force.y;var c=s.velocity.x,d=s.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=t},{}],13:[function(e,n){function t(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=t},{}],14:[function(e,n){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":24,"ngraph.random":25}],15:[function(e,n){function t(e,n,t){var o="[object Array]"===Object.prototype.toString.call(t);if(o)for(var i=0;i0&&u(s.pos,a.pos));if(0===f&&u(s.pos,a.pos))return}c.push(i,s),c.push(i,a)}else{var h=a.pos.x,m=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*h,i.massY=i.massY+a.mass*m;var y=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;if(h>w){y+=1;var L=x;x=w,w+=w-L}if(m>E){y+=2;var P=b;b=E,E+=E-P}var N=t(i,y);N?c.push(N,a):(N=v(),N.left=x,N.top=b,N.right=w,N.bottom=E,N.body=a,r(i,y,N))}}},m=function(e){var n,t,r,i,a=f,u=0,c=0,l=1,p=0,v=1;for(a[0]=g;l;){var h=a[p],m=h.body;l-=1,p+=1;var y=m!==e;m&&y?(t=m.pos.x-e.pos.x,r=m.pos.y-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),n=s*m.mass*e.mass/(i*i*i),u+=n*t,c+=n*r):y&&(t=h.massX/h.mass-e.pos.x,r=h.massY/h.mass-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),(h.right-h.left)/iu&&(t=u),u>o&&(o=u),r>s&&(r=s),s>i&&(i=s)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,p=0,g=v(),g.left=t,g.right=o,g.top=r,g.bottom=i,n=a-1,n>0&&(g.body=e[n]);n--;)h(e[n],g)};return{insertBodies:y,updateBodyForce:m,options:function(e){return e?("number"==typeof e.gravity&&(s=e.gravity),"number"==typeof e.theta&&(d=e.theta),this):{gravity:s,theta:d}}}}},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":25}],18:[function(e,n){function t(){this.stack=[],this.popIdx=0}function r(e,n){this.node=e,this.body=n}n.exports=t,t.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new r(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],19:[function(e,n){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],20:[function(e,n){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],21:[function(e,n){function t(e,n,t){var i;n=n||r,t=t||r,i="string"==typeof e?JSON.parse(e):e;var a,u=o();if(void 0===i.links||void 0===i.nodes)throw new Error("Cannot load graph without links and nodes");for(a=0;ae)throw new Error("Invalid number of nodes");var n,t=l();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function r(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=t(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function o(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=l();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function i(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=l();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function a(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=l();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function u(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=l();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function s(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=l();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var u=i*e*n,s=r+o*e+u;r>0&&a.addLink(s,r-1+o*e+u),o>0&&a.addLink(s,r+(o-1)*e+u),i>0&&a.addLink(s,r+o*e+(i-1)*e*n)}return a}function f(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=l(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function c(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=l();for(n=0;e>n;++n)t.addNode(n);return t}function d(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,u=e("ngraph.random").random(o||42),s=l();for(i=0;n>i;++i)s.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,s.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(u.nextDouble()n)return!1;B(),_.splice(n,1);var t=f(e.fromId),o=f(e.toId);return t&&(n=r(e,t.links),n>=0&&t.links.splice(n,1)),o&&(n=r(e,o.links),n>=0&&o.links.splice(n,1)),U(e,"remove"),F(),!0}function h(e,n){var t,r=f(e);if(!r)return null;for(t=0;tn;++n)e(_[n])}function x(e,n,t){var r=f(e);return r&&r.links&&"function"==typeof n?t?b(r.links,e,n):w(r.links,e,n):void 0}function w(e,n,t){for(var r,o=0;o0&&(O.fire("changed",M),M.length=0)}function N(){return Object.keys?k:A}function k(e){if("function"==typeof e)for(var n=Object.keys(j),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function o(e){this.id=e,this.links=[],this.data=null}function i(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=t;var a=e("ngraph.events")},{"ngraph.events":6}],24:[function(e,n){function t(e,n){var r;if(e||(e={}),n)for(r in n)if(n.hasOwnProperty(r)){var o=e.hasOwnProperty(r),i=typeof n[r],a=!o||typeof e[r]!==i;a?e[r]=n[r]:"object"===i&&(e[r]=t(e[r],n[r]))}return e}n.exports=t},{}],25:[function(e,n){function t(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function r(e,n){var r=n||t();if("function"!=typeof r.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var t,o,i;for(t=e.length-1;t>0;--t)o=r.next(t+1),i=e[o],e[o]=e[t],e[t]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,t,o;for(n=e.length-1;n>0;--n)t=r.next(n+1),o=e[t],e[t]=e[n],e[n]=o;return e}}}n.exports={random:t,randomIterator:r}},{}],26:[function(e,n){function t(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=t},{}],27:[function(e,n){function t(e,n){var t=r(e);if(void 0===n)return t;for(var o=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},A=function(e){p=!1,r.off("touchmove",k),r.off("touchend",A),r.off("touchcancel",A),c=null,a&&a(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,r.on("touchmove",k),r.on("touchend",A),r.on("touchcancel",A))},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return a=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),r.off("mousemove",w),r.off("mouseup",E),r.off("touchmove",k),r.off("touchend",A),r.off("touchcancel",A),P(null) +}}}n.exports=t;var r=e("../Utils/documentEvents.js"),o=e("../Utils/browserInfo.js"),i=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":39,"../Utils/documentEvents.js":40,"../Utils/findElementPosition.js":41}],36:[function(e,n){function t(e,n){var t=r(n),o=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){o=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(o);var r=i[e.id];return r&&r.onStart&&r.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(o),o=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(o){var t=i[o.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=t;var r=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":57}],37:[function(e,n){function t(e,n){function t(e){return d[e]}n=r(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var a=o(n.seed),u=new i(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(){return{x:a.next(n.maxX),y:a.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"==typeof z?z:!0}function d(){G=G||window.document.body,F=F||o(e,{springLength:80,springCoeff:2e-4}),O=O||i(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||u)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=s(function(){return p()},M)):(X=0,V=0,R=s(p,M)))}function g(){J||(W=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;en,t)}),e.forEachNode(E),T(),e.on("changed",j)}function D(){q=!1,T(),I(),a.off("resize",_),K.off(),R.stop(),e.forEachLink(function(e){n.renderLinks&&b(e)}),e.forEachNode(function(e){L(e),x(e)}),F.dispose(),N()}var M=30;n=n||{};var U,R,B,F=n.layout,O=n.graphics,G=n.container,z=void 0!==n.interactive?n.interactive:!0,q=!1,Y=!0,X=0,V=0,W=!1,H=!1,J=!1,$={offsetX:0,offsetY:0,scale:1},K=r({});return{run:function(e){return q||(d(),h(),P(),m(),S(),q=!0),v(e),this},reset:function(){O.resetScale(),m(),$.scale=1},pause:function(){J=!0,R.stop()},resume:function(){J=!1,R.restart()},rerender:function(){return l(),this},zoomOut:function(){return C(!0)},zoomIn:function(){return C(!1)},moveTo:function(e,n){O.graphCenterChanged($.offsetX-e*$.scale,$.offsetY-n*$.scale),l()},getGraphics:function(){return O},dispose:function(){D()},on:function(e,n){return K.on(e,n),this},off:function(e,n){return K.off(e,n),this}}}n.exports=t;var r=e("ngraph.events"),o=e("ngraph.forcelayout"),i=e("./svgGraphics.js"),a=e("../Utils/windowEvents.js"),u=e("../Input/domInputManager.js"),s=e("../Utils/timer.js"),f=e("../Utils/getDimensions.js"),c=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":34,"../Input/dragndrop.js":35,"../Utils/getDimensions.js":42,"../Utils/timer.js":46,"../Utils/windowEvents.js":47,"./svgGraphics.js":49,"ngraph.events":6,"ngraph.forcelayout":7}],49:[function(e,n){function t(){function e(){var e=r("svg");return n=r("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,a,u=0,s=0,f=1,c={},d={},l=function(){return r("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(){return r("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+u+","+s+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){u=e,s=n,w()},inputManager:i,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),a=n.getCTM().multiply(i);f=a.a,u=a.e,s=a.f;var c="matrix("+a.a+", 0, 0,"+a.d+","+a.e+","+a.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof a&&a(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):a=e),t},getSvgRoot:function(){return t}};return o(b),b}n.exports=t;var r=e("simplesvg"),o=e("ngraph.events"),i=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":34,"ngraph.events":6,simplesvg:27}],50:[function(e,n){function t(e){e=f(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,c,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=o(),P=i(),N=function(){return a()},k=function(){return u(3014898687)},A=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),c&&c.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(k=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:r,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,A()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],A()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,A(),I(this),y[0]},resetScale:function(){return j(),c&&(_(),A()),this},init:function(r){var o={};if(e.preserveDrawingBuffer&&(o.preserveDrawingBuffer=!0),n=r,_(),j(),n.appendChild(t),c=t.getContext("experimental-webgl",o),!c){var i="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(i),i}if(e.enableBlending&&(c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA),c.enable(c.BLEND)),e.clearColor){var a=e.clearColorValue;c.clearColor(a.r,a.g,a.b,a.a),this.beginRender=function(){c.clear(c.COLOR_BUFFER_BIT)}}L.load(c),L.updateSize(d/2,l/2),P.load(c),P.updateSize(d/2,l/2),A(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!c&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!c&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return s(T),T}n.exports=t;var r=e("../Input/webglInputManager.js"),o=e("../WebGL/webglLinkProgram.js"),i=e("../WebGL/webglNodeProgram.js"),a=e("../WebGL/webglSquare.js"),u=e("../WebGL/webglLine.js"),s=e("ngraph.events"),f=e("ngraph.merge")},{"../Input/webglInputManager.js":36,"../WebGL/webglLine.js":58,"../WebGL/webglLinkProgram.js":59,"../WebGL/webglNodeProgram.js":60,"../WebGL/webglSquare.js":61,"ngraph.events":6,"ngraph.merge":24}],51:[function(e,n){function t(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=t},{}],52:[function(e,n){function t(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=t},{}],53:[function(e,n){function t(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function i(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function o(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=t},{}],54:[function(e,n){function t(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!r(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:i,getCoordinates:a,load:u};return E}function r(e){return 0===(e&e-1)}var o=e("./texture.js");n.exports=t},{"./texture.js":52}],55:[function(e,n){function t(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=t},{}],56:[function(e,n){function t(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=r(),k=o(),A=1024,j=0,_=new Float32Array(64);return{load:t,position:u,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function r(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function o(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var i=e("./webglAtlas.js"),a=e("./webgl.js");n.exports=t},{"./webgl.js":53,"./webglAtlas.js":54}],57:[function(e,n){function t(e){function n(){x=null}function t(e){x=e}function o(e){return"function"==typeof e&&k.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(k,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],k=[],A=e.getGraphicsRoot();h(A);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:o,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var r=e("../Utils/documentEvents.js");n.exports=t},{"../Utils/documentEvents.js":40}],58:[function(e,n){function t(e){return{color:r(e)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":51}],59:[function(e,n){function t(){var e,n,t,o,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,o=r(a),e=o.createProgram(v,p),n.useProgram(e),i=o.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&o.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&o.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":53}],60:[function(e,n){function t(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=r(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function o(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(N,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:o,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":53}],61:[function(e,n){function t(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":51}],62:[function(e,n){n.exports="0.7.11"},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/package.json b/package.json index fa28fed..cf3fb24 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "gintersect": "0.1.0", "ngraph.centrality": "0.1.3", "ngraph.events": "0.0.3", - "ngraph.forcelayout": "0.0.18", + "ngraph.forcelayout": "0.0.20", "ngraph.fromjson": "0.1.7", "ngraph.generators": "0.0.15", "ngraph.graph": "0.0.11", diff --git a/src/View/renderer.js b/src/View/renderer.js index c3fc3d9..58661dd 100644 --- a/src/View/renderer.js +++ b/src/View/renderer.js @@ -186,10 +186,10 @@ function renderer(graph, settings) { function prepareSettings() { container = container || window.document.body; - layout = layout || forceDirected(graph, forceDirected.simulator({ + layout = layout || forceDirected(graph, { springLength: 80, springCoeff: 0.0002, - })); + }); graphics = graphics || svgGraphics(graph, { container: container }); diff --git a/src/version.js b/src/version.js index 317c93d..1e889df 100644 --- a/src/version.js +++ b/src/version.js @@ -1,2 +1,2 @@ // todo: this should be generated at build time. -module.exports = '0.7.10'; +module.exports = '0.7.11'; diff --git a/src/viva.js b/src/viva.js index 9513002..0ee7704 100644 --- a/src/viva.js +++ b/src/viva.js @@ -61,11 +61,7 @@ Viva.Graph = { }, Layout: { - forceDirected: function(graph, physicsSettings) { - // vivagraph had slightly different API: - var forceLayout = require('ngraph.forcelayout'); - return forceLayout(graph, forceLayout.simulator(physicsSettings)); - }, + forceDirected: require('ngraph.forcelayout'), constant: require('./Layout/constant.js') }, From 9f17a42504aea55f78fc03bbdf4a6c454efd43bd Mon Sep 17 00:00:00 2001 From: anvaka Date: Thu, 16 Apr 2015 18:23:20 -0700 Subject: [PATCH 200/276] 0.7.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cf3fb24..b1cea1d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.7.10", + "version": "0.7.11", "description": "Graph Drawing Library", "main": "src/viva", "directories": { From c32216706fd4483ddc7fe5703e7be5efbe8547d9 Mon Sep 17 00:00:00 2001 From: anvaka Date: Thu, 16 Apr 2015 20:25:59 -0700 Subject: [PATCH 201/276] Fixed https://github.com/anvaka/VivaGraphJS/issues/137 --- dist/vivagraph.js | 5 ++++- dist/vivagraph.min.js | 2 +- src/View/renderer.js | 3 +++ src/version.js | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 8142578..3373fd2 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -4582,6 +4582,9 @@ function renderer(graph, settings) { } if (isInteractive('scroll')) { + if (!containerDrag) { + containerDrag = dragndrop(container); + } containerDrag.onScroll(function(e, scaleOffset, scrollPoint) { scale(scaleOffset < 0, scrollPoint); }); @@ -6797,7 +6800,7 @@ function webglSquare(size, color) { },{"./parseColor.js":51}],62:[function(require,module,exports){ // todo: this should be generated at build time. -module.exports = '0.7.11'; +module.exports = '0.7.12'; },{}]},{},[1])(1) }); \ No newline at end of file diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index a4ed601..649fd6c 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-s*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=t},{}],3:[function(e,n){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n){function t(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function v(e){var n=w[e];n.mass=m(e)}function g(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function h(e){var n=w[e];return n||(f(e),n=w[e]),n}function m(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var y=e("ngraph.physics.simulator"),x=y(t),w="function"==typeof Object.create?Object.create(null):{},b={},E=x.settings.springTransform||r;s(),a();var L={step:function(){return x.step()},getNodePosition:function(e){return h(e).pos},setNodePosition:function(e){var n=h(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return x.getBBox()},pinNode:function(e,n){var t=h(e.id);t.isPinned=!!n},isNodePinned:function(e){return h(e.id).isPinned},dispose:function(){n.off("changed",u)},getBody:i,getSpring:o,simulator:x};return L}function r(){}n.exports=t,n.exports.simulator=e("ngraph.physics.simulator")},{"ngraph.physics.simulator":8}],8:[function(e,n){function t(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.force.reset(),v.updateBodyForce(e),m.update(e);for(n=p.length;n--;)h.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),u=n.createBounds||e("./lib/bounds"),s=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),g=u(l,n),h=f(n),m=s(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return g.update(),en))return l.splice(n,1),0===l.length&&g.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return g.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=t},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":24,"ngraph.quadtreebh":17}],9:[function(e,n){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;ut;++t){var s=e[t],f=n/s.mass;s.velocity.x+=f*s.force.x,s.velocity.y+=f*s.force.y;var c=s.velocity.x,d=s.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=t},{}],13:[function(e,n){function t(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=t},{}],14:[function(e,n){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":24,"ngraph.random":25}],15:[function(e,n){function t(e,n,t){var o="[object Array]"===Object.prototype.toString.call(t);if(o)for(var i=0;i0&&u(s.pos,a.pos));if(0===f&&u(s.pos,a.pos))return}c.push(i,s),c.push(i,a)}else{var h=a.pos.x,m=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*h,i.massY=i.massY+a.mass*m;var y=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;if(h>w){y+=1;var L=x;x=w,w+=w-L}if(m>E){y+=2;var P=b;b=E,E+=E-P}var N=t(i,y);N?c.push(N,a):(N=v(),N.left=x,N.top=b,N.right=w,N.bottom=E,N.body=a,r(i,y,N))}}},m=function(e){var n,t,r,i,a=f,u=0,c=0,l=1,p=0,v=1;for(a[0]=g;l;){var h=a[p],m=h.body;l-=1,p+=1;var y=m!==e;m&&y?(t=m.pos.x-e.pos.x,r=m.pos.y-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),n=s*m.mass*e.mass/(i*i*i),u+=n*t,c+=n*r):y&&(t=h.massX/h.mass-e.pos.x,r=h.massY/h.mass-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),(h.right-h.left)/iu&&(t=u),u>o&&(o=u),r>s&&(r=s),s>i&&(i=s)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,p=0,g=v(),g.left=t,g.right=o,g.top=r,g.bottom=i,n=a-1,n>0&&(g.body=e[n]);n--;)h(e[n],g)};return{insertBodies:y,updateBodyForce:m,options:function(e){return e?("number"==typeof e.gravity&&(s=e.gravity),"number"==typeof e.theta&&(d=e.theta),this):{gravity:s,theta:d}}}}},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":25}],18:[function(e,n){function t(){this.stack=[],this.popIdx=0}function r(e,n){this.node=e,this.body=n}n.exports=t,t.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new r(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],19:[function(e,n){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],20:[function(e,n){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],21:[function(e,n){function t(e,n,t){var i;n=n||r,t=t||r,i="string"==typeof e?JSON.parse(e):e;var a,u=o();if(void 0===i.links||void 0===i.nodes)throw new Error("Cannot load graph without links and nodes");for(a=0;ae)throw new Error("Invalid number of nodes");var n,t=l();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function r(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=t(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function o(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=l();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function i(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=l();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function a(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=l();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function u(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=l();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function s(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=l();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var u=i*e*n,s=r+o*e+u;r>0&&a.addLink(s,r-1+o*e+u),o>0&&a.addLink(s,r+(o-1)*e+u),i>0&&a.addLink(s,r+o*e+(i-1)*e*n)}return a}function f(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=l(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function c(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=l();for(n=0;e>n;++n)t.addNode(n);return t}function d(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,u=e("ngraph.random").random(o||42),s=l();for(i=0;n>i;++i)s.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,s.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(u.nextDouble()n)return!1;B(),_.splice(n,1);var t=f(e.fromId),o=f(e.toId);return t&&(n=r(e,t.links),n>=0&&t.links.splice(n,1)),o&&(n=r(e,o.links),n>=0&&o.links.splice(n,1)),U(e,"remove"),F(),!0}function h(e,n){var t,r=f(e);if(!r)return null;for(t=0;tn;++n)e(_[n])}function x(e,n,t){var r=f(e);return r&&r.links&&"function"==typeof n?t?b(r.links,e,n):w(r.links,e,n):void 0}function w(e,n,t){for(var r,o=0;o0&&(O.fire("changed",M),M.length=0)}function N(){return Object.keys?k:A}function k(e){if("function"==typeof e)for(var n=Object.keys(j),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function o(e){this.id=e,this.links=[],this.data=null}function i(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=t;var a=e("ngraph.events")},{"ngraph.events":6}],24:[function(e,n){function t(e,n){var r;if(e||(e={}),n)for(r in n)if(n.hasOwnProperty(r)){var o=e.hasOwnProperty(r),i=typeof n[r],a=!o||typeof e[r]!==i;a?e[r]=n[r]:"object"===i&&(e[r]=t(e[r],n[r]))}return e}n.exports=t},{}],25:[function(e,n){function t(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function r(e,n){var r=n||t();if("function"!=typeof r.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var t,o,i;for(t=e.length-1;t>0;--t)o=r.next(t+1),i=e[o],e[o]=e[t],e[t]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,t,o;for(n=e.length-1;n>0;--n)t=r.next(n+1),o=e[t],e[t]=e[n],e[n]=o;return e}}}n.exports={random:t,randomIterator:r}},{}],26:[function(e,n){function t(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=t},{}],27:[function(e,n){function t(e,n){var t=r(e);if(void 0===n)return t;for(var o=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},A=function(e){p=!1,r.off("touchmove",k),r.off("touchend",A),r.off("touchcancel",A),c=null,a&&a(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,r.on("touchmove",k),r.on("touchend",A),r.on("touchcancel",A))},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return a=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),r.off("mousemove",w),r.off("mouseup",E),r.off("touchmove",k),r.off("touchend",A),r.off("touchcancel",A),P(null) -}}}n.exports=t;var r=e("../Utils/documentEvents.js"),o=e("../Utils/browserInfo.js"),i=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":39,"../Utils/documentEvents.js":40,"../Utils/findElementPosition.js":41}],36:[function(e,n){function t(e,n){var t=r(n),o=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){o=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(o);var r=i[e.id];return r&&r.onStart&&r.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(o),o=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(o){var t=i[o.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=t;var r=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":57}],37:[function(e,n){function t(e,n){function t(e){return d[e]}n=r(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var a=o(n.seed),u=new i(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(){return{x:a.next(n.maxX),y:a.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"==typeof z?z:!0}function d(){G=G||window.document.body,F=F||o(e,{springLength:80,springCoeff:2e-4}),O=O||i(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||u)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=s(function(){return p()},M)):(X=0,V=0,R=s(p,M)))}function g(){J||(W=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;en,t)}),e.forEachNode(E),T(),e.on("changed",j)}function D(){q=!1,T(),I(),a.off("resize",_),K.off(),R.stop(),e.forEachLink(function(e){n.renderLinks&&b(e)}),e.forEachNode(function(e){L(e),x(e)}),F.dispose(),N()}var M=30;n=n||{};var U,R,B,F=n.layout,O=n.graphics,G=n.container,z=void 0!==n.interactive?n.interactive:!0,q=!1,Y=!0,X=0,V=0,W=!1,H=!1,J=!1,$={offsetX:0,offsetY:0,scale:1},K=r({});return{run:function(e){return q||(d(),h(),P(),m(),S(),q=!0),v(e),this},reset:function(){O.resetScale(),m(),$.scale=1},pause:function(){J=!0,R.stop()},resume:function(){J=!1,R.restart()},rerender:function(){return l(),this},zoomOut:function(){return C(!0)},zoomIn:function(){return C(!1)},moveTo:function(e,n){O.graphCenterChanged($.offsetX-e*$.scale,$.offsetY-n*$.scale),l()},getGraphics:function(){return O},dispose:function(){D()},on:function(e,n){return K.on(e,n),this},off:function(e,n){return K.off(e,n),this}}}n.exports=t;var r=e("ngraph.events"),o=e("ngraph.forcelayout"),i=e("./svgGraphics.js"),a=e("../Utils/windowEvents.js"),u=e("../Input/domInputManager.js"),s=e("../Utils/timer.js"),f=e("../Utils/getDimensions.js"),c=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":34,"../Input/dragndrop.js":35,"../Utils/getDimensions.js":42,"../Utils/timer.js":46,"../Utils/windowEvents.js":47,"./svgGraphics.js":49,"ngraph.events":6,"ngraph.forcelayout":7}],49:[function(e,n){function t(){function e(){var e=r("svg");return n=r("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,a,u=0,s=0,f=1,c={},d={},l=function(){return r("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(){return r("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+u+","+s+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){u=e,s=n,w()},inputManager:i,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),a=n.getCTM().multiply(i);f=a.a,u=a.e,s=a.f;var c="matrix("+a.a+", 0, 0,"+a.d+","+a.e+","+a.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof a&&a(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):a=e),t},getSvgRoot:function(){return t}};return o(b),b}n.exports=t;var r=e("simplesvg"),o=e("ngraph.events"),i=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":34,"ngraph.events":6,simplesvg:27}],50:[function(e,n){function t(e){e=f(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,c,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=o(),P=i(),N=function(){return a()},k=function(){return u(3014898687)},A=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),c&&c.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(k=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:r,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,A()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],A()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,A(),I(this),y[0]},resetScale:function(){return j(),c&&(_(),A()),this},init:function(r){var o={};if(e.preserveDrawingBuffer&&(o.preserveDrawingBuffer=!0),n=r,_(),j(),n.appendChild(t),c=t.getContext("experimental-webgl",o),!c){var i="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(i),i}if(e.enableBlending&&(c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA),c.enable(c.BLEND)),e.clearColor){var a=e.clearColorValue;c.clearColor(a.r,a.g,a.b,a.a),this.beginRender=function(){c.clear(c.COLOR_BUFFER_BIT)}}L.load(c),L.updateSize(d/2,l/2),P.load(c),P.updateSize(d/2,l/2),A(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!c&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!c&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return s(T),T}n.exports=t;var r=e("../Input/webglInputManager.js"),o=e("../WebGL/webglLinkProgram.js"),i=e("../WebGL/webglNodeProgram.js"),a=e("../WebGL/webglSquare.js"),u=e("../WebGL/webglLine.js"),s=e("ngraph.events"),f=e("ngraph.merge")},{"../Input/webglInputManager.js":36,"../WebGL/webglLine.js":58,"../WebGL/webglLinkProgram.js":59,"../WebGL/webglNodeProgram.js":60,"../WebGL/webglSquare.js":61,"ngraph.events":6,"ngraph.merge":24}],51:[function(e,n){function t(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=t},{}],52:[function(e,n){function t(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=t},{}],53:[function(e,n){function t(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function i(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function o(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=t},{}],54:[function(e,n){function t(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!r(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:i,getCoordinates:a,load:u};return E}function r(e){return 0===(e&e-1)}var o=e("./texture.js");n.exports=t},{"./texture.js":52}],55:[function(e,n){function t(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=t},{}],56:[function(e,n){function t(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=r(),k=o(),A=1024,j=0,_=new Float32Array(64);return{load:t,position:u,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function r(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function o(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var i=e("./webglAtlas.js"),a=e("./webgl.js");n.exports=t},{"./webgl.js":53,"./webglAtlas.js":54}],57:[function(e,n){function t(e){function n(){x=null}function t(e){x=e}function o(e){return"function"==typeof e&&k.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(k,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],k=[],A=e.getGraphicsRoot();h(A);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:o,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var r=e("../Utils/documentEvents.js");n.exports=t},{"../Utils/documentEvents.js":40}],58:[function(e,n){function t(e){return{color:r(e)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":51}],59:[function(e,n){function t(){var e,n,t,o,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,o=r(a),e=o.createProgram(v,p),n.useProgram(e),i=o.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&o.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&o.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":53}],60:[function(e,n){function t(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=r(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function o(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(N,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:o,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":53}],61:[function(e,n){function t(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":51}],62:[function(e,n){n.exports="0.7.11"},{}]},{},[1])(1)}); \ No newline at end of file +}}}n.exports=t;var r=e("../Utils/documentEvents.js"),o=e("../Utils/browserInfo.js"),i=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":39,"../Utils/documentEvents.js":40,"../Utils/findElementPosition.js":41}],36:[function(e,n){function t(e,n){var t=r(n),o=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){o=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(o);var r=i[e.id];return r&&r.onStart&&r.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(o),o=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(o){var t=i[o.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=t;var r=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":57}],37:[function(e,n){function t(e,n){function t(e){return d[e]}n=r(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var a=o(n.seed),u=new i(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(){return{x:a.next(n.maxX),y:a.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"==typeof z?z:!0}function d(){G=G||window.document.body,F=F||o(e,{springLength:80,springCoeff:2e-4}),O=O||i(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||u)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=s(function(){return p()},M)):(X=0,V=0,R=s(p,M)))}function g(){J||(W=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;en,t)})),e.forEachNode(E),T(),e.on("changed",j)}function D(){q=!1,T(),I(),a.off("resize",_),K.off(),R.stop(),e.forEachLink(function(e){n.renderLinks&&b(e)}),e.forEachNode(function(e){L(e),x(e)}),F.dispose(),N()}var M=30;n=n||{};var U,R,B,F=n.layout,O=n.graphics,G=n.container,z=void 0!==n.interactive?n.interactive:!0,q=!1,Y=!0,X=0,V=0,W=!1,H=!1,J=!1,$={offsetX:0,offsetY:0,scale:1},K=r({});return{run:function(e){return q||(d(),h(),P(),m(),S(),q=!0),v(e),this},reset:function(){O.resetScale(),m(),$.scale=1},pause:function(){J=!0,R.stop()},resume:function(){J=!1,R.restart()},rerender:function(){return l(),this},zoomOut:function(){return C(!0)},zoomIn:function(){return C(!1)},moveTo:function(e,n){O.graphCenterChanged($.offsetX-e*$.scale,$.offsetY-n*$.scale),l()},getGraphics:function(){return O},dispose:function(){D()},on:function(e,n){return K.on(e,n),this},off:function(e,n){return K.off(e,n),this}}}n.exports=t;var r=e("ngraph.events"),o=e("ngraph.forcelayout"),i=e("./svgGraphics.js"),a=e("../Utils/windowEvents.js"),u=e("../Input/domInputManager.js"),s=e("../Utils/timer.js"),f=e("../Utils/getDimensions.js"),c=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":34,"../Input/dragndrop.js":35,"../Utils/getDimensions.js":42,"../Utils/timer.js":46,"../Utils/windowEvents.js":47,"./svgGraphics.js":49,"ngraph.events":6,"ngraph.forcelayout":7}],49:[function(e,n){function t(){function e(){var e=r("svg");return n=r("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,a,u=0,s=0,f=1,c={},d={},l=function(){return r("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(){return r("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+u+","+s+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){u=e,s=n,w()},inputManager:i,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),a=n.getCTM().multiply(i);f=a.a,u=a.e,s=a.f;var c="matrix("+a.a+", 0, 0,"+a.d+","+a.e+","+a.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof a&&a(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):a=e),t},getSvgRoot:function(){return t}};return o(b),b}n.exports=t;var r=e("simplesvg"),o=e("ngraph.events"),i=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":34,"ngraph.events":6,simplesvg:27}],50:[function(e,n){function t(e){e=f(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,c,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=o(),P=i(),N=function(){return a()},k=function(){return u(3014898687)},A=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),c&&c.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(k=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:r,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,A()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],A()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,A(),I(this),y[0]},resetScale:function(){return j(),c&&(_(),A()),this},init:function(r){var o={};if(e.preserveDrawingBuffer&&(o.preserveDrawingBuffer=!0),n=r,_(),j(),n.appendChild(t),c=t.getContext("experimental-webgl",o),!c){var i="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(i),i}if(e.enableBlending&&(c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA),c.enable(c.BLEND)),e.clearColor){var a=e.clearColorValue;c.clearColor(a.r,a.g,a.b,a.a),this.beginRender=function(){c.clear(c.COLOR_BUFFER_BIT)}}L.load(c),L.updateSize(d/2,l/2),P.load(c),P.updateSize(d/2,l/2),A(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!c&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!c&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return s(T),T}n.exports=t;var r=e("../Input/webglInputManager.js"),o=e("../WebGL/webglLinkProgram.js"),i=e("../WebGL/webglNodeProgram.js"),a=e("../WebGL/webglSquare.js"),u=e("../WebGL/webglLine.js"),s=e("ngraph.events"),f=e("ngraph.merge")},{"../Input/webglInputManager.js":36,"../WebGL/webglLine.js":58,"../WebGL/webglLinkProgram.js":59,"../WebGL/webglNodeProgram.js":60,"../WebGL/webglSquare.js":61,"ngraph.events":6,"ngraph.merge":24}],51:[function(e,n){function t(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=t},{}],52:[function(e,n){function t(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=t},{}],53:[function(e,n){function t(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function i(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function o(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=t},{}],54:[function(e,n){function t(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!r(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:i,getCoordinates:a,load:u};return E}function r(e){return 0===(e&e-1)}var o=e("./texture.js");n.exports=t},{"./texture.js":52}],55:[function(e,n){function t(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=t},{}],56:[function(e,n){function t(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=r(),k=o(),A=1024,j=0,_=new Float32Array(64);return{load:t,position:u,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function r(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function o(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var i=e("./webglAtlas.js"),a=e("./webgl.js");n.exports=t},{"./webgl.js":53,"./webglAtlas.js":54}],57:[function(e,n){function t(e){function n(){x=null}function t(e){x=e}function o(e){return"function"==typeof e&&k.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(k,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],k=[],A=e.getGraphicsRoot();h(A);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:o,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var r=e("../Utils/documentEvents.js");n.exports=t},{"../Utils/documentEvents.js":40}],58:[function(e,n){function t(e){return{color:r(e)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":51}],59:[function(e,n){function t(){var e,n,t,o,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,o=r(a),e=o.createProgram(v,p),n.useProgram(e),i=o.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&o.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&o.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":53}],60:[function(e,n){function t(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=r(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function o(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(N,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:o,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":53}],61:[function(e,n){function t(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":51}],62:[function(e,n){n.exports="0.7.12"},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/src/View/renderer.js b/src/View/renderer.js index 58661dd..558cb85 100644 --- a/src/View/renderer.js +++ b/src/View/renderer.js @@ -439,6 +439,9 @@ function renderer(graph, settings) { } if (isInteractive('scroll')) { + if (!containerDrag) { + containerDrag = dragndrop(container); + } containerDrag.onScroll(function(e, scaleOffset, scrollPoint) { scale(scaleOffset < 0, scrollPoint); }); diff --git a/src/version.js b/src/version.js index 1e889df..826e08e 100644 --- a/src/version.js +++ b/src/version.js @@ -1,2 +1,2 @@ // todo: this should be generated at build time. -module.exports = '0.7.11'; +module.exports = '0.7.12'; From 01432d7789b8e7e21c30da50c4068e989af3e8aa Mon Sep 17 00:00:00 2001 From: anvaka Date: Thu, 16 Apr 2015 20:26:11 -0700 Subject: [PATCH 202/276] 0.7.12 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b1cea1d..e377dfa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.7.11", + "version": "0.7.12", "description": "Graph Drawing Library", "main": "src/viva", "directories": { From 8da433b296a7cd702a44249df30b4fc04c249610 Mon Sep 17 00:00:00 2001 From: Kevin Kirsche Date: Fri, 12 Jun 2015 18:08:08 -0400 Subject: [PATCH 203/276] Remove moot `version` property from bower.json Per bower/bower.json-spec@a325da3 Also their maintainer says they probably won't ever use it: http://stackoverflow.com/questions/24844901/bowers-bower-json-file-version-property --- bower.json | 1 - 1 file changed, 1 deletion(-) diff --git a/bower.json b/bower.json index 155f8f5..c937a4d 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,5 @@ { "name": "vivagraphjs", - "version": "0.6.3", "homepage": "https://github.com/anvaka/VivaGraphJS", "authors": [ "anvaka " From 1422d87a300cff22187c4e00570c3432897d5564 Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 24 Jun 2015 09:16:17 -0700 Subject: [PATCH 204/276] Fix for https://github.com/anvaka/VivaGraphJS/issues/149 --- demos/other/dynamicNodeChange.html | 31 ++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/demos/other/dynamicNodeChange.html b/demos/other/dynamicNodeChange.html index d8de1f4..379e5af 100644 --- a/demos/other/dynamicNodeChange.html +++ b/demos/other/dynamicNodeChange.html @@ -17,17 +17,7 @@ }); var graphics = Viva.Graph.View.svgGraphics(); - graphics.node(function(node){ - var ui = Viva.Graph.svg('rect') - .attr('width', node.data.width) - .attr('height', node.data.height) - .attr('fill', '#00ef00'); - ui.data = node.data; - return ui; - }).placeNode(function(nodeUI, pos) { - nodeUI.attr('x', pos.x - nodeUI.data.width/2) - .attr('y', pos.y - nodeUI.data.height/2); - }); + graphics.node(createNodeUI).placeNode(placeNode); var renderer = Viva.Graph.View.renderer(graph, { layout : layout, @@ -60,7 +50,24 @@ if (factor < 0 || factor > 10) { direction *= -1; } - }, 30) + }, 30); + + function createNodeUI(node){ + var ui = Viva.Graph.svg('rect') + .attr('width', node.data.width) + .attr('height', node.data.height) + .attr('fill', '#00ef00'); + ui.data = node.data; + + var pos = layout.getNodePosition(node.id); + placeNode(ui, pos); + return ui; + } + + function placeNode(nodeUI, pos) { + nodeUI.attr('x', pos.x - nodeUI.data.width/2) + .attr('y', pos.y - nodeUI.data.height/2); + } } + + + + + From d65150bfd42afba7d9bb4b3884b0bb2c99ad8c55 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 18 Jul 2015 12:52:14 -0700 Subject: [PATCH 206/276] Updating to latest force layout Comes with increased speed for graphs with pinned nodes --- dist/vivagraph.js | 12 ++++++++---- dist/vivagraph.min.js | 4 ++-- package.json | 2 +- src/version.js | 2 +- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 3373fd2..2414c3f 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -1026,10 +1026,14 @@ function physicsSimulator(settings) { quadTree.insertBodies(bodies); // performance: O(n * log n) while (i--) { body = bodies[i]; - body.force.reset(); + // If body is pinned there is no point updating its forces - it should + // never move: + if (!body.isPinned) { + body.force.reset(); - quadTree.updateBodyForce(body); - dragForce.update(body); + quadTree.updateBodyForce(body); + dragForce.update(body); + } } } @@ -6800,7 +6804,7 @@ function webglSquare(size, color) { },{"./parseColor.js":51}],62:[function(require,module,exports){ // todo: this should be generated at build time. -module.exports = '0.7.12'; +module.exports = '0.7.13'; },{}]},{},[1])(1) }); \ No newline at end of file diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 649fd6c..5543157 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-s*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=t},{}],3:[function(e,n){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n){function t(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function v(e){var n=w[e];n.mass=m(e)}function g(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function h(e){var n=w[e];return n||(f(e),n=w[e]),n}function m(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var y=e("ngraph.physics.simulator"),x=y(t),w="function"==typeof Object.create?Object.create(null):{},b={},E=x.settings.springTransform||r;s(),a();var L={step:function(){return x.step()},getNodePosition:function(e){return h(e).pos},setNodePosition:function(e){var n=h(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return x.getBBox()},pinNode:function(e,n){var t=h(e.id);t.isPinned=!!n},isNodePinned:function(e){return h(e.id).isPinned},dispose:function(){n.off("changed",u)},getBody:i,getSpring:o,simulator:x};return L}function r(){}n.exports=t,n.exports.simulator=e("ngraph.physics.simulator")},{"ngraph.physics.simulator":8}],8:[function(e,n){function t(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.force.reset(),v.updateBodyForce(e),m.update(e);for(n=p.length;n--;)h.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),u=n.createBounds||e("./lib/bounds"),s=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),g=u(l,n),h=f(n),m=s(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return g.update(),en))return l.splice(n,1),0===l.length&&g.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return g.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=t},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":24,"ngraph.quadtreebh":17}],9:[function(e,n){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;ut;++t){var s=e[t],f=n/s.mass;s.velocity.x+=f*s.force.x,s.velocity.y+=f*s.force.y;var c=s.velocity.x,d=s.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=t},{}],13:[function(e,n){function t(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=t},{}],14:[function(e,n){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":24,"ngraph.random":25}],15:[function(e,n){function t(e,n,t){var o="[object Array]"===Object.prototype.toString.call(t);if(o)for(var i=0;i0&&u(s.pos,a.pos));if(0===f&&u(s.pos,a.pos))return}c.push(i,s),c.push(i,a)}else{var h=a.pos.x,m=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*h,i.massY=i.massY+a.mass*m;var y=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;if(h>w){y+=1;var L=x;x=w,w+=w-L}if(m>E){y+=2;var P=b;b=E,E+=E-P}var N=t(i,y);N?c.push(N,a):(N=v(),N.left=x,N.top=b,N.right=w,N.bottom=E,N.body=a,r(i,y,N))}}},m=function(e){var n,t,r,i,a=f,u=0,c=0,l=1,p=0,v=1;for(a[0]=g;l;){var h=a[p],m=h.body;l-=1,p+=1;var y=m!==e;m&&y?(t=m.pos.x-e.pos.x,r=m.pos.y-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),n=s*m.mass*e.mass/(i*i*i),u+=n*t,c+=n*r):y&&(t=h.massX/h.mass-e.pos.x,r=h.massY/h.mass-e.pos.y,i=Math.sqrt(t*t+r*r),0===i&&(t=(o.nextDouble()-.5)/50,r=(o.nextDouble()-.5)/50,i=Math.sqrt(t*t+r*r)),(h.right-h.left)/iu&&(t=u),u>o&&(o=u),r>s&&(r=s),s>i&&(i=s)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,p=0,g=v(),g.left=t,g.right=o,g.top=r,g.bottom=i,n=a-1,n>0&&(g.body=e[n]);n--;)h(e[n],g)};return{insertBodies:y,updateBodyForce:m,options:function(e){return e?("number"==typeof e.gravity&&(s=e.gravity),"number"==typeof e.theta&&(d=e.theta),this):{gravity:s,theta:d}}}}},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":25}],18:[function(e,n){function t(){this.stack=[],this.popIdx=0}function r(e,n){this.node=e,this.body=n}n.exports=t,t.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new r(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],19:[function(e,n){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],20:[function(e,n){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],21:[function(e,n){function t(e,n,t){var i;n=n||r,t=t||r,i="string"==typeof e?JSON.parse(e):e;var a,u=o();if(void 0===i.links||void 0===i.nodes)throw new Error("Cannot load graph without links and nodes");for(a=0;ae)throw new Error("Invalid number of nodes");var n,t=l();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function r(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=t(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function o(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=l();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function i(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=l();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function a(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=l();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function u(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=l();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function s(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=l();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var u=i*e*n,s=r+o*e+u;r>0&&a.addLink(s,r-1+o*e+u),o>0&&a.addLink(s,r+(o-1)*e+u),i>0&&a.addLink(s,r+o*e+(i-1)*e*n)}return a}function f(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=l(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function c(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=l();for(n=0;e>n;++n)t.addNode(n);return t}function d(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,u=e("ngraph.random").random(o||42),s=l();for(i=0;n>i;++i)s.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,s.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(u.nextDouble()n)return!1;B(),_.splice(n,1);var t=f(e.fromId),o=f(e.toId);return t&&(n=r(e,t.links),n>=0&&t.links.splice(n,1)),o&&(n=r(e,o.links),n>=0&&o.links.splice(n,1)),U(e,"remove"),F(),!0}function h(e,n){var t,r=f(e);if(!r)return null;for(t=0;tn;++n)e(_[n])}function x(e,n,t){var r=f(e);return r&&r.links&&"function"==typeof n?t?b(r.links,e,n):w(r.links,e,n):void 0}function w(e,n,t){for(var r,o=0;o0&&(O.fire("changed",M),M.length=0)}function N(){return Object.keys?k:A}function k(e){if("function"==typeof e)for(var n=Object.keys(j),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function o(e){this.id=e,this.links=[],this.data=null}function i(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=t;var a=e("ngraph.events")},{"ngraph.events":6}],24:[function(e,n){function t(e,n){var r;if(e||(e={}),n)for(r in n)if(n.hasOwnProperty(r)){var o=e.hasOwnProperty(r),i=typeof n[r],a=!o||typeof e[r]!==i;a?e[r]=n[r]:"object"===i&&(e[r]=t(e[r],n[r]))}return e}n.exports=t},{}],25:[function(e,n){function t(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function r(e,n){var r=n||t();if("function"!=typeof r.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var t,o,i;for(t=e.length-1;t>0;--t)o=r.next(t+1),i=e[o],e[o]=e[t],e[t]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,t,o;for(n=e.length-1;n>0;--n)t=r.next(n+1),o=e[t],e[t]=e[n],e[n]=o;return e}}}n.exports={random:t,randomIterator:r}},{}],26:[function(e,n){function t(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=t},{}],27:[function(e,n){function t(e,n){var t=r(e);if(void 0===n)return t;for(var o=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},A=function(e){p=!1,r.off("touchmove",k),r.off("touchend",A),r.off("touchcancel",A),c=null,a&&a(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,r.on("touchmove",k),r.on("touchend",A),r.on("touchcancel",A))},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return a=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),r.off("mousemove",w),r.off("mouseup",E),r.off("touchmove",k),r.off("touchend",A),r.off("touchcancel",A),P(null) -}}}n.exports=t;var r=e("../Utils/documentEvents.js"),o=e("../Utils/browserInfo.js"),i=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":39,"../Utils/documentEvents.js":40,"../Utils/findElementPosition.js":41}],36:[function(e,n){function t(e,n){var t=r(n),o=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){o=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(o);var r=i[e.id];return r&&r.onStart&&r.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(o),o=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(o){var t=i[o.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=t;var r=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":57}],37:[function(e,n){function t(e,n){function t(e){return d[e]}n=r(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var a=o(n.seed),u=new i(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(){return{x:a.next(n.maxX),y:a.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"==typeof z?z:!0}function d(){G=G||window.document.body,F=F||o(e,{springLength:80,springCoeff:2e-4}),O=O||i(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||u)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=s(function(){return p()},M)):(X=0,V=0,R=s(p,M)))}function g(){J||(W=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;en,t)})),e.forEachNode(E),T(),e.on("changed",j)}function D(){q=!1,T(),I(),a.off("resize",_),K.off(),R.stop(),e.forEachLink(function(e){n.renderLinks&&b(e)}),e.forEachNode(function(e){L(e),x(e)}),F.dispose(),N()}var M=30;n=n||{};var U,R,B,F=n.layout,O=n.graphics,G=n.container,z=void 0!==n.interactive?n.interactive:!0,q=!1,Y=!0,X=0,V=0,W=!1,H=!1,J=!1,$={offsetX:0,offsetY:0,scale:1},K=r({});return{run:function(e){return q||(d(),h(),P(),m(),S(),q=!0),v(e),this},reset:function(){O.resetScale(),m(),$.scale=1},pause:function(){J=!0,R.stop()},resume:function(){J=!1,R.restart()},rerender:function(){return l(),this},zoomOut:function(){return C(!0)},zoomIn:function(){return C(!1)},moveTo:function(e,n){O.graphCenterChanged($.offsetX-e*$.scale,$.offsetY-n*$.scale),l()},getGraphics:function(){return O},dispose:function(){D()},on:function(e,n){return K.on(e,n),this},off:function(e,n){return K.off(e,n),this}}}n.exports=t;var r=e("ngraph.events"),o=e("ngraph.forcelayout"),i=e("./svgGraphics.js"),a=e("../Utils/windowEvents.js"),u=e("../Input/domInputManager.js"),s=e("../Utils/timer.js"),f=e("../Utils/getDimensions.js"),c=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":34,"../Input/dragndrop.js":35,"../Utils/getDimensions.js":42,"../Utils/timer.js":46,"../Utils/windowEvents.js":47,"./svgGraphics.js":49,"ngraph.events":6,"ngraph.forcelayout":7}],49:[function(e,n){function t(){function e(){var e=r("svg");return n=r("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,a,u=0,s=0,f=1,c={},d={},l=function(){return r("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(){return r("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+u+","+s+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){u=e,s=n,w()},inputManager:i,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),a=n.getCTM().multiply(i);f=a.a,u=a.e,s=a.f;var c="matrix("+a.a+", 0, 0,"+a.d+","+a.e+","+a.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof a&&a(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):a=e),t},getSvgRoot:function(){return t}};return o(b),b}n.exports=t;var r=e("simplesvg"),o=e("ngraph.events"),i=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":34,"ngraph.events":6,simplesvg:27}],50:[function(e,n){function t(e){e=f(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,c,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=o(),P=i(),N=function(){return a()},k=function(){return u(3014898687)},A=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),c&&c.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(k=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:r,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,A()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],A()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,A(),I(this),y[0]},resetScale:function(){return j(),c&&(_(),A()),this},init:function(r){var o={};if(e.preserveDrawingBuffer&&(o.preserveDrawingBuffer=!0),n=r,_(),j(),n.appendChild(t),c=t.getContext("experimental-webgl",o),!c){var i="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(i),i}if(e.enableBlending&&(c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA),c.enable(c.BLEND)),e.clearColor){var a=e.clearColorValue;c.clearColor(a.r,a.g,a.b,a.a),this.beginRender=function(){c.clear(c.COLOR_BUFFER_BIT)}}L.load(c),L.updateSize(d/2,l/2),P.load(c),P.updateSize(d/2,l/2),A(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!c&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!c&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return s(T),T}n.exports=t;var r=e("../Input/webglInputManager.js"),o=e("../WebGL/webglLinkProgram.js"),i=e("../WebGL/webglNodeProgram.js"),a=e("../WebGL/webglSquare.js"),u=e("../WebGL/webglLine.js"),s=e("ngraph.events"),f=e("ngraph.merge")},{"../Input/webglInputManager.js":36,"../WebGL/webglLine.js":58,"../WebGL/webglLinkProgram.js":59,"../WebGL/webglNodeProgram.js":60,"../WebGL/webglSquare.js":61,"ngraph.events":6,"ngraph.merge":24}],51:[function(e,n){function t(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=t},{}],52:[function(e,n){function t(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=t},{}],53:[function(e,n){function t(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function i(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function o(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=t},{}],54:[function(e,n){function t(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!r(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:i,getCoordinates:a,load:u};return E}function r(e){return 0===(e&e-1)}var o=e("./texture.js");n.exports=t},{"./texture.js":52}],55:[function(e,n){function t(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=t},{}],56:[function(e,n){function t(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=r(),k=o(),A=1024,j=0,_=new Float32Array(64);return{load:t,position:u,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function r(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function o(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var i=e("./webglAtlas.js"),a=e("./webgl.js");n.exports=t},{"./webgl.js":53,"./webglAtlas.js":54}],57:[function(e,n){function t(e){function n(){x=null}function t(e){x=e}function o(e){return"function"==typeof e&&k.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(k,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],k=[],A=e.getGraphicsRoot();h(A);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:o,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var r=e("../Utils/documentEvents.js");n.exports=t},{"../Utils/documentEvents.js":40}],58:[function(e,n){function t(e){return{color:r(e)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":51}],59:[function(e,n){function t(){var e,n,t,o,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,o=r(a),e=o.createProgram(v,p),n.useProgram(e),i=o.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&o.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&o.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":53}],60:[function(e,n){function t(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=r(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function o(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(N,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:o,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var r=e("./webgl.js");n.exports=t},{"./webgl.js":53}],61:[function(e,n){function t(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}var r=e("./parseColor.js");n.exports=t},{"./parseColor.js":51}],62:[function(e,n){n.exports="0.7.12"},{}]},{},[1])(1)}); \ No newline at end of file +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-s*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=r},{}],3:[function(e,n,t){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n,t){function r(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function v(e){var n=w[e];n.mass=m(e)}function g(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function h(e){var n=w[e];return n||(f(e),n=w[e]),n}function m(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var y=e("ngraph.physics.simulator"),x=y(t),w="function"==typeof Object.create?Object.create(null):{},b={},E=x.settings.springTransform||o;s(),a();var L={step:function(){return x.step()},getNodePosition:function(e){return h(e).pos},setNodePosition:function(e){var n=h(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return x.getBBox()},pinNode:function(e,n){var t=h(e.id);t.isPinned=!!n},isNodePinned:function(e){return h(e.id).isPinned},dispose:function(){n.off("changed",u)},getBody:i,getSpring:r,simulator:x};return L}function o(){}n.exports=r,n.exports.simulator=e("ngraph.physics.simulator")},{"ngraph.physics.simulator":8}],8:[function(e,n,t){function r(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.isPinned||(e.force.reset(),v.updateBodyForce(e),m.update(e));for(n=p.length;n--;)h.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),u=n.createBounds||e("./lib/bounds"),s=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),g=u(l,n),h=f(n),m=s(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return g.update(),en))return l.splice(n,1),0===l.length&&g.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return g.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=r},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":24,"ngraph.quadtreebh":17}],9:[function(e,n,t){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;ut;++t){var s=e[t],f=n/s.mass;s.velocity.x+=f*s.force.x,s.velocity.y+=f*s.force.y;var c=s.velocity.x,d=s.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=r},{}],13:[function(e,n,t){function r(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=r},{}],14:[function(e,n,t){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":24,"ngraph.random":25}],15:[function(e,n,t){function r(e,n,t){var r="[object Array]"===Object.prototype.toString.call(t);if(r)for(var i=0;i0&&u(s.pos,a.pos));if(0===f&&u(s.pos,a.pos))return}c.push(i,s),c.push(i,a)}else{var h=a.pos.x,m=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*h,i.massY=i.massY+a.mass*m;var y=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;if(h>w){y+=1;var L=x;x=w,w+=w-L}if(m>E){y+=2;var P=b;b=E,E+=E-P}var N=r(i,y);N?c.push(N,a):(N=v(),N.left=x,N.top=b,N.right=w,N.bottom=E,N.body=a,o(i,y,N))}}},m=function(e){var n,r,o,i,a=f,u=0,c=0,l=1,p=0,v=1;for(a[0]=g;l;){var h=a[p],m=h.body;l-=1,p+=1;var y=m!==e;m&&y?(r=m.pos.x-e.pos.x,o=m.pos.y-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),n=s*m.mass*e.mass/(i*i*i),u+=n*r,c+=n*o):y&&(r=h.massX/h.mass-e.pos.x,o=h.massY/h.mass-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),(h.right-h.left)/iu&&(t=u),u>o&&(o=u),r>s&&(r=s),s>i&&(i=s)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,p=0,g=v(),g.left=t,g.right=o,g.top=r,g.bottom=i,n=a-1,n>0&&(g.body=e[n]);n--;)h(e[n],g)};return{insertBodies:y,updateBodyForce:m,options:function(e){return e?("number"==typeof e.gravity&&(s=e.gravity),"number"==typeof e.theta&&(d=e.theta),this):{gravity:s,theta:d}}}}},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":25}],18:[function(e,n,t){function r(){this.stack=[],this.popIdx=0}function o(e,n){this.node=e,this.body=n}n.exports=r,r.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new o(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],19:[function(e,n,t){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],20:[function(e,n,t){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],21:[function(e,n,t){function r(e,n,t){var r;n=n||o,t=t||o,r="string"==typeof e?JSON.parse(e):e;var a,u=i();if(void 0===r.links||void 0===r.nodes)throw new Error("Cannot load graph without links and nodes");for(a=0;ae)throw new Error("Invalid number of nodes");var n,t=p();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function o(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=r(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function i(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=p();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function a(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=p();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function u(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=p();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function s(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=p();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function f(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=p();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var u=i*e*n,s=r+o*e+u;r>0&&a.addLink(s,r-1+o*e+u),o>0&&a.addLink(s,r+(o-1)*e+u),i>0&&a.addLink(s,r+o*e+(i-1)*e*n)}return a}function c(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=p(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function d(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=p();for(n=0;e>n;++n)t.addNode(n);return t}function l(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,u=e("ngraph.random").random(o||42),s=p();for(i=0;n>i;++i)s.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,s.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(u.nextDouble()n)return!1;B(),_.splice(n,1);var t=f(e.fromId),r=f(e.toId);return t&&(n=o(e,t.links),n>=0&&t.links.splice(n,1)),r&&(n=o(e,r.links),n>=0&&r.links.splice(n,1)),U(e,"remove"),F(),!0}function h(e,n){var t,r=f(e);if(!r)return null;for(t=0;tn;++n)e(_[n])}function x(e,n,t){var r=f(e);return r&&r.links&&"function"==typeof n?t?b(r.links,e,n):w(r.links,e,n):void 0}function w(e,n,t){for(var r,o=0;o0&&(O.fire("changed",M),M.length=0)}function N(){return Object.keys?k:A}function k(e){if("function"==typeof e)for(var n=Object.keys(j),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function i(e){this.id=e,this.links=[],this.data=null}function a(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=r;var u=e("ngraph.events")},{"ngraph.events":6}],24:[function(e,n,t){function r(e,n){var t;if(e||(e={}),n)for(t in n)if(n.hasOwnProperty(t)){var o=e.hasOwnProperty(t),i=typeof n[t],a=!o||typeof e[t]!==i;a?e[t]=n[t]:"object"===i&&(e[t]=r(e[t],n[t]))}return e}n.exports=r},{}],25:[function(e,n,t){function r(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function o(e,n){var t=n||r();if("function"!=typeof t.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var r,o,i;for(r=e.length-1;r>0;--r)o=t.next(r+1),i=e[o],e[o]=e[r],e[r]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,r,o;for(n=e.length-1;n>0;--n)r=t.next(n+1),o=e[r],e[r]=e[n],e[n]=o;return e}}}n.exports={random:r,randomIterator:o}},{}],26:[function(e,n,t){function r(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=r},{}],27:[function(e,n,t){function r(e,n){var t=o(e);if(void 0===n)return t;for(var r=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},A=function(e){p=!1,o.off("touchmove",k),o.off("touchend",A),o.off("touchcancel",A),c=null,r&&r(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,o.on("touchmove",k),o.on("touchend",A),o.on("touchcancel",A))},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b), +e.removeEventListener("touchstart",_),o.off("mousemove",w),o.off("mouseup",E),o.off("touchmove",k),o.off("touchend",A),o.off("touchcancel",A),P(null)}}}n.exports=r;var o=e("../Utils/documentEvents.js"),i=e("../Utils/browserInfo.js"),a=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":39,"../Utils/documentEvents.js":40,"../Utils/findElementPosition.js":41}],36:[function(e,n,t){function r(e,n){var t=o(n),r=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){r=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(r);var o=i[e.id];return o&&o.onStart&&o.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(r),r=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(r){var t=i[r.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=r;var o=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":57}],37:[function(e,n,t){function r(e,n){function t(e){return d[e]}n=o(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var r=i(n.seed),u=new a(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(e){return{x:r.next(n.maxX),y:r.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"==typeof z?z:!0}function r(){G=G||window.document.body,F=F||i(e,{springLength:80,springCoeff:2e-4}),O=O||a(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||s)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=f(function(){return p()},M)):(X=0,V=0,R=f(p,M)))}function g(){J||(W=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;en,t)})),e.forEachNode(E),T(),e.on("changed",j)}function D(){q=!1,T(),I(),u.off("resize",_),K.off(),R.stop(),e.forEachLink(function(e){n.renderLinks&&b(e)}),e.forEachNode(function(e){L(e),x(e)}),F.dispose(),N()}var M=30;n=n||{};var U,R,B,F=n.layout,O=n.graphics,G=n.container,z=void 0!==n.interactive?n.interactive:!0,q=!1,Y=!0,X=0,V=0,W=!1,H=!1,J=!1,$={offsetX:0,offsetY:0,scale:1},K=o({});return{run:function(e){return q||(r(),h(),P(),m(),S(),q=!0),v(e),this},reset:function(){O.resetScale(),m(),$.scale=1},pause:function(){J=!0,R.stop()},resume:function(){J=!1,R.restart()},rerender:function(){return l(),this},zoomOut:function(){return C(!0)},zoomIn:function(){return C(!1)},moveTo:function(e,n){O.graphCenterChanged($.offsetX-e*$.scale,$.offsetY-n*$.scale),l()},getGraphics:function(){return O},dispose:function(){D()},on:function(e,n){return K.on(e,n),this},off:function(e,n){return K.off(e,n),this}}}n.exports=r;var o=e("ngraph.events"),i=e("ngraph.forcelayout"),a=e("./svgGraphics.js"),u=e("../Utils/windowEvents.js"),s=e("../Input/domInputManager.js"),f=e("../Utils/timer.js"),c=e("../Utils/getDimensions.js"),d=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":34,"../Input/dragndrop.js":35,"../Utils/getDimensions.js":42,"../Utils/timer.js":46,"../Utils/windowEvents.js":47,"./svgGraphics.js":49,"ngraph.events":6,"ngraph.forcelayout":7}],49:[function(e,n,t){function r(){function e(){var e=o("svg");return n=o("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,r,u=0,s=0,f=1,c={},d={},l=function(e){return o("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(e){return o("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+u+","+s+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){u=e,s=n,w()},inputManager:a,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),a=n.getCTM().multiply(i);f=a.a,u=a.e,s=a.f;var c="matrix("+a.a+", 0, 0,"+a.d+","+a.e+","+a.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof r&&r(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):r=e),t},getSvgRoot:function(){return t}};return i(b),b}n.exports=r;var o=e("simplesvg"),i=e("ngraph.events"),a=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":34,"ngraph.events":6,simplesvg:27}],50:[function(e,n,t){function r(e){e=c(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,r,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=i(),P=a(),N=function(e){return u()},k=function(e){return s(3014898687)},A=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),r&&r.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(k=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:o,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,A()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],A()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,A(),I(this),y[0]},resetScale:function(){return j(),r&&(_(),A()),this},init:function(o){var i={};if(e.preserveDrawingBuffer&&(i.preserveDrawingBuffer=!0),n=o,_(),j(),n.appendChild(t),r=t.getContext("experimental-webgl",i),!r){var a="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(a),a}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var u=e.clearColorValue;r.clearColor(u.r,u.g,u.b,u.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}L.load(r),L.updateSize(d/2,l/2),P.load(r),P.updateSize(d/2,l/2),A(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!r&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!r&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return f(T),T}n.exports=r;var o=e("../Input/webglInputManager.js"),i=e("../WebGL/webglLinkProgram.js"),a=e("../WebGL/webglNodeProgram.js"),u=e("../WebGL/webglSquare.js"),s=e("../WebGL/webglLine.js"),f=e("ngraph.events"),c=e("ngraph.merge")},{"../Input/webglInputManager.js":36,"../WebGL/webglLine.js":58,"../WebGL/webglLinkProgram.js":59,"../WebGL/webglNodeProgram.js":60,"../WebGL/webglSquare.js":61,"ngraph.events":6,"ngraph.merge":24}],51:[function(e,n,t){function r(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=r},{}],52:[function(e,n,t){function r(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=r},{}],53:[function(e,n,t){function r(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function r(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function i(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=r},{}],54:[function(e,n,t){function r(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!o(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:r,getCoordinates:a,load:u};return E}function o(e){return 0===(e&e-1)}var i=e("./texture.js");n.exports=r},{"./texture.js":52}],55:[function(e,n,t){function r(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=r},{}],56:[function(e,n,t){function r(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=o(),k=i(),A=1024,j=0,_=new Float32Array(64);return{load:t,position:r,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function o(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function i(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var a=e("./webglAtlas.js"),u=e("./webgl.js");n.exports=r},{"./webgl.js":53,"./webglAtlas.js":54}],57:[function(e,n,t){function r(e){function n(){x=null}function t(e){x=e}function r(e){return"function"==typeof e&&k.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(k,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],k=[],A=e.getGraphicsRoot();h(A);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:r,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var o=e("../Utils/documentEvents.js");n.exports=r},{"../Utils/documentEvents.js":40}],58:[function(e,n,t){function r(e){return{color:o(e)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],59:[function(e,n,t){function r(){var e,n,t,r,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,r=o(a),e=r.createProgram(v,p),n.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&r.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&r.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],60:[function(e,n,t){function r(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=o(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function r(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(N,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:r,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],61:[function(e,n,t){function r(e,n){return{size:"number"==typeof e?e:10,color:o(n)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],62:[function(e,n,t){n.exports="0.7.13"},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/package.json b/package.json index e377dfa..c99e7a2 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "gintersect": "0.1.0", "ngraph.centrality": "0.1.3", "ngraph.events": "0.0.3", - "ngraph.forcelayout": "0.0.20", + "ngraph.forcelayout": "0.0.21", "ngraph.fromjson": "0.1.7", "ngraph.generators": "0.0.15", "ngraph.graph": "0.0.11", diff --git a/src/version.js b/src/version.js index 826e08e..c6bd126 100644 --- a/src/version.js +++ b/src/version.js @@ -1,2 +1,2 @@ // todo: this should be generated at build time. -module.exports = '0.7.12'; +module.exports = '0.7.13'; From c8a09b4863c854120aad1192d2127de59e4cdd39 Mon Sep 17 00:00:00 2001 From: Andrei Kashcha Date: Mon, 20 Jul 2015 01:42:12 -0700 Subject: [PATCH 207/276] Update README.md --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 954d058..44add2d 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,7 @@ VivaGraph [![Build Status](https://travis-ci.org/anvaka/VivaGraphJS.svg)](https://travis-ci.org/anvaka/VivaGraphJS) ================================================== -**VivaGraphJS** is a free [graph drawing](http://en.wikipedia.org/wiki/Graph_drawing) -library for JavaScript. It is designed to be extensible and to support different -rendering engines and layout algorithms. At the moment it supports rendering -graphs using WebGL and SVG. +**VivaGraphJS** is the fastest graph drawing javascript library [proof](https://www.youtube.com/watch?v=Ax7KSQZ0_hk). It is designed to be extensible and to support different +rendering engines and layout algorithms. Underlying modules can be found via [ngraph](https://www.npmjs.com/search?q=ngraph) query. [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/anvaka/VivaGraphJS?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) From 9a4eaa20d73b6c56905682539341ef63d563c5c4 Mon Sep 17 00:00:00 2001 From: Andrei Kashcha Date: Mon, 20 Jul 2015 01:42:39 -0700 Subject: [PATCH 208/276] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 44add2d..9243cfd 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ VivaGraph [![Build Status](https://travis-ci.org/anvaka/VivaGraphJS.svg)](https://travis-ci.org/anvaka/VivaGraphJS) ================================================== -**VivaGraphJS** is the fastest graph drawing javascript library [proof](https://www.youtube.com/watch?v=Ax7KSQZ0_hk). It is designed to be extensible and to support different +**VivaGraphJS** is the fastest graph drawing javascript library ([proof](https://www.youtube.com/watch?v=Ax7KSQZ0_hk)). It is designed to be extensible and to support different rendering engines and layout algorithms. Underlying modules can be found via [ngraph](https://www.npmjs.com/search?q=ngraph) query. [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/anvaka/VivaGraphJS?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) From 6cd0fca785c34b0091880ef2fac37f6e32f3278e Mon Sep 17 00:00:00 2001 From: Ryan Shipp Date: Fri, 24 Jul 2015 14:40:32 -0600 Subject: [PATCH 209/276] Change git URL to https GitHub no longer offers cloning over git:// protocol --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9243cfd..7a9a173 100644 --- a/README.md +++ b/README.md @@ -177,7 +177,7 @@ Local Build ----------- Run the following script: ``` -git clone git://github.com/anvaka/VivaGraphJS.git +git clone https://github.com/anvaka/VivaGraphJS.git cd ./VivaGraphJS npm install gulp release From 5527819ec5df29ef0917097d3cad60f99b13cd8e Mon Sep 17 00:00:00 2001 From: Andrei Kashcha Date: Mon, 31 Aug 2015 22:40:10 -0700 Subject: [PATCH 210/276] Update graph_intro.md --- docs/graph_intro.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/graph_intro.md b/docs/graph_intro.md index 89b0d3f..a93e158 100644 --- a/docs/graph_intro.md +++ b/docs/graph_intro.md @@ -107,4 +107,4 @@ g.forEachLinkedNode('hello', function(linkedNode, link){ }); ``` -Stop now and play with [interactive fiddle](http://jsfiddle.net/anvaka/JA76K/2/) for this article. \ No newline at end of file +Stop now and play with [interactive fiddle](http://jsfiddle.net/JA76K/182/) for this article. From 411d62f690817729f7003bb7b38dfeb69afbd386 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Thu, 10 Sep 2015 12:30:13 +1000 Subject: [PATCH 211/276] Add DOM label example --- demos/other/webglDOMLabels.html | 66 +++++++++++++++++++++++++++++++++ src/View/webglGraphics.js | 49 +++++++++++++++++------- 2 files changed, 101 insertions(+), 14 deletions(-) create mode 100644 demos/other/webglDOMLabels.html diff --git a/demos/other/webglDOMLabels.html b/demos/other/webglDOMLabels.html new file mode 100644 index 0000000..52d2708 --- /dev/null +++ b/demos/other/webglDOMLabels.html @@ -0,0 +1,66 @@ + + + + + VivaGraphs WebGL DOM Label test page + + + + + + + This is webgl renderer. You can drag a node and see the console for logs + X + + diff --git a/src/View/webglGraphics.js b/src/View/webglGraphics.js index 57aad91..736632c 100644 --- a/src/View/webglGraphics.js +++ b/src/View/webglGraphics.js @@ -502,20 +502,41 @@ function webglGraphics(options) { // TODO: unload old shader and reinit. } }, - transformClientToGraphCoordinates : function (graphicsRootPos) { - // TODO: could be a problem when container has margins? - // to save memory we modify incoming parameter: - // point in clipspace coordinates: - graphicsRootPos.x = 2 * graphicsRootPos.x / width - 1; - graphicsRootPos.y = 1 - (2 * graphicsRootPos.y) / height; - // apply transform: - graphicsRootPos.x = (graphicsRootPos.x - transform[12]) / transform[0]; - graphicsRootPos.y = (graphicsRootPos.y - transform[13]) / transform[5]; - // now transform to graph coordinates: - graphicsRootPos.x *= width / 2; - graphicsRootPos.y *= -height / 2; - - return graphicsRootPos; + + // TODO: could be a problem when container has margins? + // mutates p + transformClientToGraphCoordinates: function (p) { + // normalize + p.x = ((2 * p.x) / width) - 1 + p.y = 1 - ((2 * p.y) / height) + + // apply transform + p.x = (p.x - transform[12]) / transform[0] + p.y = (p.y - transform[13]) / transform[5] + + // transform to graph coordinates + p.x = p.x * (width / 2) + p.y = p.y * (-height / 2) + + return p + }, + + // TODO: could be a problem when container has margins? + // mutates p + transformGraphToClientCoordinates: function (p) { + // transform from graph coordinates + p.x = p.x / (width / 2) + p.y = p.y / (-height / 2) + + // apply transform + p.x = (p.x * transform[0]) + transform[12] + p.y = (p.y * transform[5]) + transform[13] + + // denormalize + p.x = ((p.x + 1) * width) / 2 + p.y = ((1 - p.y) * height) / 2 + + return p }, getNodeAtClientPos: function (clientPos, preciseCheck) { From 6fa8973417e77d9ad44db9a9f60e52c85f337654 Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 9 Sep 2015 23:24:04 -0700 Subject: [PATCH 212/276] Generalized webgl labels example --- demos/other/webglDOMLabels.html | 84 ++++++++++++++++++++++----------- dist/vivagraph.js | 49 +++++++++++++------ dist/vivagraph.min.js | 2 +- src/View/webglGraphics.js | 49 ++++++++++++------- 4 files changed, 123 insertions(+), 61 deletions(-) diff --git a/demos/other/webglDOMLabels.html b/demos/other/webglDOMLabels.html index 52d2708..15ba44a 100644 --- a/demos/other/webglDOMLabels.html +++ b/demos/other/webglDOMLabels.html @@ -8,10 +8,14 @@ - This is webgl renderer. You can drag a node and see the console for logs - X + This is webgl renderer. Labels are rendered as DOM nodes diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 2414c3f..5001d17 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -5487,20 +5487,41 @@ function webglGraphics(options) { // TODO: unload old shader and reinit. } }, - transformClientToGraphCoordinates : function (graphicsRootPos) { - // TODO: could be a problem when container has margins? - // to save memory we modify incoming parameter: - // point in clipspace coordinates: - graphicsRootPos.x = 2 * graphicsRootPos.x / width - 1; - graphicsRootPos.y = 1 - (2 * graphicsRootPos.y) / height; - // apply transform: - graphicsRootPos.x = (graphicsRootPos.x - transform[12]) / transform[0]; - graphicsRootPos.y = (graphicsRootPos.y - transform[13]) / transform[5]; - // now transform to graph coordinates: - graphicsRootPos.x *= width / 2; - graphicsRootPos.y *= -height / 2; - - return graphicsRootPos; + + // TODO: could be a problem when container has margins? + // mutates p + transformClientToGraphCoordinates: function (p) { + // normalize + p.x = ((2 * p.x) / width) - 1 + p.y = 1 - ((2 * p.y) / height) + + // apply transform + p.x = (p.x - transform[12]) / transform[0] + p.y = (p.y - transform[13]) / transform[5] + + // transform to graph coordinates + p.x = p.x * (width / 2) + p.y = p.y * (-height / 2) + + return p + }, + + // TODO: could be a problem when container has margins? + // mutates p + transformGraphToClientCoordinates: function (p) { + // transform from graph coordinates + p.x = p.x / (width / 2) + p.y = p.y / (-height / 2) + + // apply transform + p.x = (p.x * transform[0]) + transform[12] + p.y = (p.y * transform[5]) + transform[13] + + // denormalize + p.x = ((p.x + 1) * width) / 2 + p.y = ((1 - p.y) * height) / 2 + + return p }, getNodeAtClientPos: function (clientPos, preciseCheck) { diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 5543157..ec11e04 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-s*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=r},{}],3:[function(e,n,t){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n,t){function r(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function v(e){var n=w[e];n.mass=m(e)}function g(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function h(e){var n=w[e];return n||(f(e),n=w[e]),n}function m(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var y=e("ngraph.physics.simulator"),x=y(t),w="function"==typeof Object.create?Object.create(null):{},b={},E=x.settings.springTransform||o;s(),a();var L={step:function(){return x.step()},getNodePosition:function(e){return h(e).pos},setNodePosition:function(e){var n=h(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return x.getBBox()},pinNode:function(e,n){var t=h(e.id);t.isPinned=!!n},isNodePinned:function(e){return h(e.id).isPinned},dispose:function(){n.off("changed",u)},getBody:i,getSpring:r,simulator:x};return L}function o(){}n.exports=r,n.exports.simulator=e("ngraph.physics.simulator")},{"ngraph.physics.simulator":8}],8:[function(e,n,t){function r(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.isPinned||(e.force.reset(),v.updateBodyForce(e),m.update(e));for(n=p.length;n--;)h.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),u=n.createBounds||e("./lib/bounds"),s=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),g=u(l,n),h=f(n),m=s(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return g.update(),en))return l.splice(n,1),0===l.length&&g.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return g.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=r},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":24,"ngraph.quadtreebh":17}],9:[function(e,n,t){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;ut;++t){var s=e[t],f=n/s.mass;s.velocity.x+=f*s.force.x,s.velocity.y+=f*s.force.y;var c=s.velocity.x,d=s.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=r},{}],13:[function(e,n,t){function r(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=r},{}],14:[function(e,n,t){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":24,"ngraph.random":25}],15:[function(e,n,t){function r(e,n,t){var r="[object Array]"===Object.prototype.toString.call(t);if(r)for(var i=0;i0&&u(s.pos,a.pos));if(0===f&&u(s.pos,a.pos))return}c.push(i,s),c.push(i,a)}else{var h=a.pos.x,m=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*h,i.massY=i.massY+a.mass*m;var y=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;if(h>w){y+=1;var L=x;x=w,w+=w-L}if(m>E){y+=2;var P=b;b=E,E+=E-P}var N=r(i,y);N?c.push(N,a):(N=v(),N.left=x,N.top=b,N.right=w,N.bottom=E,N.body=a,o(i,y,N))}}},m=function(e){var n,r,o,i,a=f,u=0,c=0,l=1,p=0,v=1;for(a[0]=g;l;){var h=a[p],m=h.body;l-=1,p+=1;var y=m!==e;m&&y?(r=m.pos.x-e.pos.x,o=m.pos.y-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),n=s*m.mass*e.mass/(i*i*i),u+=n*r,c+=n*o):y&&(r=h.massX/h.mass-e.pos.x,o=h.massY/h.mass-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),(h.right-h.left)/iu&&(t=u),u>o&&(o=u),r>s&&(r=s),s>i&&(i=s)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,p=0,g=v(),g.left=t,g.right=o,g.top=r,g.bottom=i,n=a-1,n>0&&(g.body=e[n]);n--;)h(e[n],g)};return{insertBodies:y,updateBodyForce:m,options:function(e){return e?("number"==typeof e.gravity&&(s=e.gravity),"number"==typeof e.theta&&(d=e.theta),this):{gravity:s,theta:d}}}}},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":25}],18:[function(e,n,t){function r(){this.stack=[],this.popIdx=0}function o(e,n){this.node=e,this.body=n}n.exports=r,r.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new o(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],19:[function(e,n,t){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],20:[function(e,n,t){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],21:[function(e,n,t){function r(e,n,t){var r;n=n||o,t=t||o,r="string"==typeof e?JSON.parse(e):e;var a,u=i();if(void 0===r.links||void 0===r.nodes)throw new Error("Cannot load graph without links and nodes");for(a=0;ae)throw new Error("Invalid number of nodes");var n,t=p();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function o(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=r(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function i(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=p();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function a(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=p();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function u(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=p();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function s(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=p();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function f(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=p();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var u=i*e*n,s=r+o*e+u;r>0&&a.addLink(s,r-1+o*e+u),o>0&&a.addLink(s,r+(o-1)*e+u),i>0&&a.addLink(s,r+o*e+(i-1)*e*n)}return a}function c(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=p(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function d(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=p();for(n=0;e>n;++n)t.addNode(n);return t}function l(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,u=e("ngraph.random").random(o||42),s=p();for(i=0;n>i;++i)s.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,s.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(u.nextDouble()n)return!1;B(),_.splice(n,1);var t=f(e.fromId),r=f(e.toId);return t&&(n=o(e,t.links),n>=0&&t.links.splice(n,1)),r&&(n=o(e,r.links),n>=0&&r.links.splice(n,1)),U(e,"remove"),F(),!0}function h(e,n){var t,r=f(e);if(!r)return null;for(t=0;tn;++n)e(_[n])}function x(e,n,t){var r=f(e);return r&&r.links&&"function"==typeof n?t?b(r.links,e,n):w(r.links,e,n):void 0}function w(e,n,t){for(var r,o=0;o0&&(O.fire("changed",M),M.length=0)}function N(){return Object.keys?k:A}function k(e){if("function"==typeof e)for(var n=Object.keys(j),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function i(e){this.id=e,this.links=[],this.data=null}function a(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=r;var u=e("ngraph.events")},{"ngraph.events":6}],24:[function(e,n,t){function r(e,n){var t;if(e||(e={}),n)for(t in n)if(n.hasOwnProperty(t)){var o=e.hasOwnProperty(t),i=typeof n[t],a=!o||typeof e[t]!==i;a?e[t]=n[t]:"object"===i&&(e[t]=r(e[t],n[t]))}return e}n.exports=r},{}],25:[function(e,n,t){function r(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function o(e,n){var t=n||r();if("function"!=typeof t.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var r,o,i;for(r=e.length-1;r>0;--r)o=t.next(r+1),i=e[o],e[o]=e[r],e[r]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,r,o;for(n=e.length-1;n>0;--n)r=t.next(n+1),o=e[r],e[r]=e[n],e[n]=o;return e}}}n.exports={random:r,randomIterator:o}},{}],26:[function(e,n,t){function r(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=r},{}],27:[function(e,n,t){function r(e,n){var t=o(e);if(void 0===n)return t;for(var r=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},A=function(e){p=!1,o.off("touchmove",k),o.off("touchend",A),o.off("touchcancel",A),c=null,r&&r(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,o.on("touchmove",k),o.on("touchend",A),o.on("touchcancel",A))},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b), -e.removeEventListener("touchstart",_),o.off("mousemove",w),o.off("mouseup",E),o.off("touchmove",k),o.off("touchend",A),o.off("touchcancel",A),P(null)}}}n.exports=r;var o=e("../Utils/documentEvents.js"),i=e("../Utils/browserInfo.js"),a=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":39,"../Utils/documentEvents.js":40,"../Utils/findElementPosition.js":41}],36:[function(e,n,t){function r(e,n){var t=o(n),r=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){r=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(r);var o=i[e.id];return o&&o.onStart&&o.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(r),r=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(r){var t=i[r.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=r;var o=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":57}],37:[function(e,n,t){function r(e,n){function t(e){return d[e]}n=o(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var r=i(n.seed),u=new a(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(e){return{x:r.next(n.maxX),y:r.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"==typeof z?z:!0}function r(){G=G||window.document.body,F=F||i(e,{springLength:80,springCoeff:2e-4}),O=O||a(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||s)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=f(function(){return p()},M)):(X=0,V=0,R=f(p,M)))}function g(){J||(W=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;en,t)})),e.forEachNode(E),T(),e.on("changed",j)}function D(){q=!1,T(),I(),u.off("resize",_),K.off(),R.stop(),e.forEachLink(function(e){n.renderLinks&&b(e)}),e.forEachNode(function(e){L(e),x(e)}),F.dispose(),N()}var M=30;n=n||{};var U,R,B,F=n.layout,O=n.graphics,G=n.container,z=void 0!==n.interactive?n.interactive:!0,q=!1,Y=!0,X=0,V=0,W=!1,H=!1,J=!1,$={offsetX:0,offsetY:0,scale:1},K=o({});return{run:function(e){return q||(r(),h(),P(),m(),S(),q=!0),v(e),this},reset:function(){O.resetScale(),m(),$.scale=1},pause:function(){J=!0,R.stop()},resume:function(){J=!1,R.restart()},rerender:function(){return l(),this},zoomOut:function(){return C(!0)},zoomIn:function(){return C(!1)},moveTo:function(e,n){O.graphCenterChanged($.offsetX-e*$.scale,$.offsetY-n*$.scale),l()},getGraphics:function(){return O},dispose:function(){D()},on:function(e,n){return K.on(e,n),this},off:function(e,n){return K.off(e,n),this}}}n.exports=r;var o=e("ngraph.events"),i=e("ngraph.forcelayout"),a=e("./svgGraphics.js"),u=e("../Utils/windowEvents.js"),s=e("../Input/domInputManager.js"),f=e("../Utils/timer.js"),c=e("../Utils/getDimensions.js"),d=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":34,"../Input/dragndrop.js":35,"../Utils/getDimensions.js":42,"../Utils/timer.js":46,"../Utils/windowEvents.js":47,"./svgGraphics.js":49,"ngraph.events":6,"ngraph.forcelayout":7}],49:[function(e,n,t){function r(){function e(){var e=o("svg");return n=o("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,r,u=0,s=0,f=1,c={},d={},l=function(e){return o("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(e){return o("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+u+","+s+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){u=e,s=n,w()},inputManager:a,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),a=n.getCTM().multiply(i);f=a.a,u=a.e,s=a.f;var c="matrix("+a.a+", 0, 0,"+a.d+","+a.e+","+a.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof r&&r(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):r=e),t},getSvgRoot:function(){return t}};return i(b),b}n.exports=r;var o=e("simplesvg"),i=e("ngraph.events"),a=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":34,"ngraph.events":6,simplesvg:27}],50:[function(e,n,t){function r(e){e=c(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,r,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=i(),P=a(),N=function(e){return u()},k=function(e){return s(3014898687)},A=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),r&&r.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(k=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:o,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,A()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],A()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,A(),I(this),y[0]},resetScale:function(){return j(),r&&(_(),A()),this},init:function(o){var i={};if(e.preserveDrawingBuffer&&(i.preserveDrawingBuffer=!0),n=o,_(),j(),n.appendChild(t),r=t.getContext("experimental-webgl",i),!r){var a="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(a),a}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var u=e.clearColorValue;r.clearColor(u.r,u.g,u.b,u.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}L.load(r),L.updateSize(d/2,l/2),P.load(r),P.updateSize(d/2,l/2),A(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!r&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!r&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x*=d/2,e.y*=-l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return f(T),T}n.exports=r;var o=e("../Input/webglInputManager.js"),i=e("../WebGL/webglLinkProgram.js"),a=e("../WebGL/webglNodeProgram.js"),u=e("../WebGL/webglSquare.js"),s=e("../WebGL/webglLine.js"),f=e("ngraph.events"),c=e("ngraph.merge")},{"../Input/webglInputManager.js":36,"../WebGL/webglLine.js":58,"../WebGL/webglLinkProgram.js":59,"../WebGL/webglNodeProgram.js":60,"../WebGL/webglSquare.js":61,"ngraph.events":6,"ngraph.merge":24}],51:[function(e,n,t){function r(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=r},{}],52:[function(e,n,t){function r(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=r},{}],53:[function(e,n,t){function r(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function r(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function i(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=r},{}],54:[function(e,n,t){function r(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!o(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:r,getCoordinates:a,load:u};return E}function o(e){return 0===(e&e-1)}var i=e("./texture.js");n.exports=r},{"./texture.js":52}],55:[function(e,n,t){function r(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=r},{}],56:[function(e,n,t){function r(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=o(),k=i(),A=1024,j=0,_=new Float32Array(64);return{load:t,position:r,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function o(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function i(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var a=e("./webglAtlas.js"),u=e("./webgl.js");n.exports=r},{"./webgl.js":53,"./webglAtlas.js":54}],57:[function(e,n,t){function r(e){function n(){x=null}function t(e){x=e}function r(e){return"function"==typeof e&&k.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(k,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],k=[],A=e.getGraphicsRoot();h(A);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:r,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var o=e("../Utils/documentEvents.js");n.exports=r},{"../Utils/documentEvents.js":40}],58:[function(e,n,t){function r(e){return{color:o(e)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],59:[function(e,n,t){function r(){var e,n,t,r,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,r=o(a),e=r.createProgram(v,p),n.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&r.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&r.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],60:[function(e,n,t){function r(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=o(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function r(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(N,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:r,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],61:[function(e,n,t){function r(e,n){return{size:"number"==typeof e?e:10,color:o(n)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],62:[function(e,n,t){n.exports="0.7.13"},{}]},{},[1])(1)}); \ No newline at end of file +e.removeEventListener("touchstart",_),o.off("mousemove",w),o.off("mouseup",E),o.off("touchmove",k),o.off("touchend",A),o.off("touchcancel",A),P(null)}}}n.exports=r;var o=e("../Utils/documentEvents.js"),i=e("../Utils/browserInfo.js"),a=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":39,"../Utils/documentEvents.js":40,"../Utils/findElementPosition.js":41}],36:[function(e,n,t){function r(e,n){var t=o(n),r=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){r=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(r);var o=i[e.id];return o&&o.onStart&&o.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(r),r=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(r){var t=i[r.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=r;var o=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":57}],37:[function(e,n,t){function r(e,n){function t(e){return d[e]}n=o(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var r=i(n.seed),u=new a(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(e){return{x:r.next(n.maxX),y:r.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"==typeof z?z:!0}function r(){G=G||window.document.body,F=F||i(e,{springLength:80,springCoeff:2e-4}),O=O||a(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||s)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=f(function(){return p()},M)):(X=0,V=0,R=f(p,M)))}function g(){J||(W=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;en,t)})),e.forEachNode(E),T(),e.on("changed",j)}function D(){q=!1,T(),I(),u.off("resize",_),K.off(),R.stop(),e.forEachLink(function(e){n.renderLinks&&b(e)}),e.forEachNode(function(e){L(e),x(e)}),F.dispose(),N()}var M=30;n=n||{};var U,R,B,F=n.layout,O=n.graphics,G=n.container,z=void 0!==n.interactive?n.interactive:!0,q=!1,Y=!0,X=0,V=0,W=!1,H=!1,J=!1,$={offsetX:0,offsetY:0,scale:1},K=o({});return{run:function(e){return q||(r(),h(),P(),m(),S(),q=!0),v(e),this},reset:function(){O.resetScale(),m(),$.scale=1},pause:function(){J=!0,R.stop()},resume:function(){J=!1,R.restart()},rerender:function(){return l(),this},zoomOut:function(){return C(!0)},zoomIn:function(){return C(!1)},moveTo:function(e,n){O.graphCenterChanged($.offsetX-e*$.scale,$.offsetY-n*$.scale),l()},getGraphics:function(){return O},dispose:function(){D()},on:function(e,n){return K.on(e,n),this},off:function(e,n){return K.off(e,n),this}}}n.exports=r;var o=e("ngraph.events"),i=e("ngraph.forcelayout"),a=e("./svgGraphics.js"),u=e("../Utils/windowEvents.js"),s=e("../Input/domInputManager.js"),f=e("../Utils/timer.js"),c=e("../Utils/getDimensions.js"),d=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":34,"../Input/dragndrop.js":35,"../Utils/getDimensions.js":42,"../Utils/timer.js":46,"../Utils/windowEvents.js":47,"./svgGraphics.js":49,"ngraph.events":6,"ngraph.forcelayout":7}],49:[function(e,n,t){function r(){function e(){var e=o("svg");return n=o("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,r,u=0,s=0,f=1,c={},d={},l=function(e){return o("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(e){return o("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+u+","+s+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){u=e,s=n,w()},inputManager:a,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),a=n.getCTM().multiply(i);f=a.a,u=a.e,s=a.f;var c="matrix("+a.a+", 0, 0,"+a.d+","+a.e+","+a.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof r&&r(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):r=e),t},getSvgRoot:function(){return t}};return i(b),b}n.exports=r;var o=e("simplesvg"),i=e("ngraph.events"),a=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":34,"ngraph.events":6,simplesvg:27}],50:[function(e,n,t){function r(e){e=c(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,r,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=i(),P=a(),N=function(e){return u()},k=function(e){return s(3014898687)},A=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),r&&r.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(k=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:o,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,A()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],A()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,A(),I(this),y[0]},resetScale:function(){return j(),r&&(_(),A()),this},init:function(o){var i={};if(e.preserveDrawingBuffer&&(i.preserveDrawingBuffer=!0),n=o,_(),j(),n.appendChild(t),r=t.getContext("experimental-webgl",i),!r){var a="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(a),a}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var u=e.clearColorValue;r.clearColor(u.r,u.g,u.b,u.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}L.load(r),L.updateSize(d/2,l/2),P.load(r),P.updateSize(d/2,l/2),A(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!r&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!r&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x=e.x*(d/2),e.y=e.y*(-l/2),e},transformGraphToClientCoordinates:function(e){return e.x=e.x/(d/2),e.y=e.y/(-l/2),e.x=e.x*y[0]+y[12],e.y=e.y*y[5]+y[13],e.x=(e.x+1)*d/2,e.y=(1-e.y)*l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return f(T),T}n.exports=r;var o=e("../Input/webglInputManager.js"),i=e("../WebGL/webglLinkProgram.js"),a=e("../WebGL/webglNodeProgram.js"),u=e("../WebGL/webglSquare.js"),s=e("../WebGL/webglLine.js"),f=e("ngraph.events"),c=e("ngraph.merge")},{"../Input/webglInputManager.js":36,"../WebGL/webglLine.js":58,"../WebGL/webglLinkProgram.js":59,"../WebGL/webglNodeProgram.js":60,"../WebGL/webglSquare.js":61,"ngraph.events":6,"ngraph.merge":24}],51:[function(e,n,t){function r(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=r},{}],52:[function(e,n,t){function r(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=r},{}],53:[function(e,n,t){function r(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function r(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function i(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=r},{}],54:[function(e,n,t){function r(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!o(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:r,getCoordinates:a,load:u};return E}function o(e){return 0===(e&e-1)}var i=e("./texture.js");n.exports=r},{"./texture.js":52}],55:[function(e,n,t){function r(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=r},{}],56:[function(e,n,t){function r(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=o(),k=i(),A=1024,j=0,_=new Float32Array(64);return{load:t,position:r,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function o(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function i(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var a=e("./webglAtlas.js"),u=e("./webgl.js");n.exports=r},{"./webgl.js":53,"./webglAtlas.js":54}],57:[function(e,n,t){function r(e){function n(){x=null}function t(e){x=e}function r(e){return"function"==typeof e&&k.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(k,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],k=[],A=e.getGraphicsRoot();h(A);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:r,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var o=e("../Utils/documentEvents.js");n.exports=r},{"../Utils/documentEvents.js":40}],58:[function(e,n,t){function r(e){return{color:o(e)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],59:[function(e,n,t){function r(){var e,n,t,r,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,r=o(a),e=r.createProgram(v,p),n.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&r.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&r.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],60:[function(e,n,t){function r(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=o(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function r(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(N,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:r,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],61:[function(e,n,t){function r(e,n){return{size:"number"==typeof e?e:10,color:o(n)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],62:[function(e,n,t){n.exports="0.7.13"},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/src/View/webglGraphics.js b/src/View/webglGraphics.js index 736632c..5c9ad58 100644 --- a/src/View/webglGraphics.js +++ b/src/View/webglGraphics.js @@ -503,40 +503,53 @@ function webglGraphics(options) { } }, - // TODO: could be a problem when container has margins? - // mutates p + /** + * Transforms client coordinates into layout coordinates. Client coordinates + * are DOM coordinates relative to the rendering container. Layout + * coordinates are those assigned by by layout algorithm to each node. + * + * @param {Object} p - a point object with `x` and `y` attributes. + * This method mutates p. + */ transformClientToGraphCoordinates: function (p) { + // TODO: could be a problem when container has margins? // normalize - p.x = ((2 * p.x) / width) - 1 - p.y = 1 - ((2 * p.y) / height) + p.x = ((2 * p.x) / width) - 1; + p.y = 1 - ((2 * p.y) / height); // apply transform - p.x = (p.x - transform[12]) / transform[0] - p.y = (p.y - transform[13]) / transform[5] + p.x = (p.x - transform[12]) / transform[0]; + p.y = (p.y - transform[13]) / transform[5]; // transform to graph coordinates - p.x = p.x * (width / 2) - p.y = p.y * (-height / 2) + p.x = p.x * (width / 2); + p.y = p.y * (-height / 2); - return p + return p; }, - // TODO: could be a problem when container has margins? - // mutates p + /** + * Transforms WebGL coordinates into client coordinates. Reverse of + * `transformClientToGraphCoordinates()` + * + * @param {Object} p - a point object with `x` and `y` attributes, which + * represents a layout coordinate. This method mutates p. + */ transformGraphToClientCoordinates: function (p) { + // TODO: could be a problem when container has margins? // transform from graph coordinates - p.x = p.x / (width / 2) - p.y = p.y / (-height / 2) + p.x = p.x / (width / 2); + p.y = p.y / (-height / 2); // apply transform - p.x = (p.x * transform[0]) + transform[12] - p.y = (p.y * transform[5]) + transform[13] + p.x = (p.x * transform[0]) + transform[12]; + p.y = (p.y * transform[5]) + transform[13]; // denormalize - p.x = ((p.x + 1) * width) / 2 - p.y = ((1 - p.y) * height) / 2 + p.x = ((p.x + 1) * width) / 2; + p.y = ((1 - p.y) * height) / 2; - return p + return p; }, getNodeAtClientPos: function (clientPos, preciseCheck) { From a31096d8abc8181945fe793d5026f37a0e21c411 Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 9 Sep 2015 23:37:41 -0700 Subject: [PATCH 213/276] webglGraphics now report correct node position Previously it was favoring shader's coordinates over actual layout coordinates. This change breaks expectations of the custom shaders code. To fix the expectation just reverse the y coordinate of your `position()` code in node shader. --- demos/other/webglCustomNode.html | 2 +- dist/vivagraph.js | 53 ++++++++++++++++++++------------ dist/vivagraph.min.js | 2 +- src/View/webglGraphics.js | 2 +- src/WebGL/webglNodeProgram.js | 2 +- 5 files changed, 37 insertions(+), 24 deletions(-) diff --git a/demos/other/webglCustomNode.html b/demos/other/webglCustomNode.html index 1bcefff..77760c4 100644 --- a/demos/other/webglCustomNode.html +++ b/demos/other/webglCustomNode.html @@ -126,7 +126,7 @@ position : function (nodeUI, pos) { var idx = nodeUI.id; nodes[idx * ATTRIBUTES_PER_PRIMITIVE] = pos.x; - nodes[idx * ATTRIBUTES_PER_PRIMITIVE + 1] = pos.y; + nodes[idx * ATTRIBUTES_PER_PRIMITIVE + 1] = -pos.y; nodes[idx * ATTRIBUTES_PER_PRIMITIVE + 2] = nodeUI.color; nodes[idx * ATTRIBUTES_PER_PRIMITIVE + 3] = nodeUI.size; }, diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 5001d17..cff3af6 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -5411,7 +5411,7 @@ function webglGraphics(options) { for (var i = 0; i < nodesCount; ++i) { var ui = nodes[i]; pos.x = ui.position.x; - pos.y = -ui.position.y; + pos.y = ui.position.y; if (userPlaceNodeCallback) { userPlaceNodeCallback(ui, pos); } @@ -5488,40 +5488,53 @@ function webglGraphics(options) { } }, - // TODO: could be a problem when container has margins? - // mutates p + /** + * Transforms client coordinates into layout coordinates. Client coordinates + * are DOM coordinates relative to the rendering container. Layout + * coordinates are those assigned by by layout algorithm to each node. + * + * @param {Object} p - a point object with `x` and `y` attributes. + * This method mutates p. + */ transformClientToGraphCoordinates: function (p) { + // TODO: could be a problem when container has margins? // normalize - p.x = ((2 * p.x) / width) - 1 - p.y = 1 - ((2 * p.y) / height) + p.x = ((2 * p.x) / width) - 1; + p.y = 1 - ((2 * p.y) / height); // apply transform - p.x = (p.x - transform[12]) / transform[0] - p.y = (p.y - transform[13]) / transform[5] + p.x = (p.x - transform[12]) / transform[0]; + p.y = (p.y - transform[13]) / transform[5]; // transform to graph coordinates - p.x = p.x * (width / 2) - p.y = p.y * (-height / 2) + p.x = p.x * (width / 2); + p.y = p.y * (-height / 2); - return p + return p; }, - // TODO: could be a problem when container has margins? - // mutates p + /** + * Transforms WebGL coordinates into client coordinates. Reverse of + * `transformClientToGraphCoordinates()` + * + * @param {Object} p - a point object with `x` and `y` attributes, which + * represents a layout coordinate. This method mutates p. + */ transformGraphToClientCoordinates: function (p) { + // TODO: could be a problem when container has margins? // transform from graph coordinates - p.x = p.x / (width / 2) - p.y = p.y / (-height / 2) + p.x = p.x / (width / 2); + p.y = p.y / (-height / 2); // apply transform - p.x = (p.x * transform[0]) + transform[12] - p.y = (p.y * transform[5]) + transform[13] + p.x = (p.x * transform[0]) + transform[12]; + p.y = (p.y * transform[5]) + transform[13]; // denormalize - p.x = ((p.x + 1) * width) / 2 - p.y = ((1 - p.y) * height) / 2 + p.x = ((p.x + 1) * width) / 2; + p.y = ((1 - p.y) * height) / 2; - return p + return p; }, getNodeAtClientPos: function (clientPos, preciseCheck) { @@ -6744,7 +6757,7 @@ function webglNodeProgram() { var idx = nodeUI.id; positions[idx * ATTRIBUTES_PER_PRIMITIVE] = pos.x; - positions[idx * ATTRIBUTES_PER_PRIMITIVE + 1] = pos.y; + positions[idx * ATTRIBUTES_PER_PRIMITIVE + 1] = -pos.y; positions[idx * ATTRIBUTES_PER_PRIMITIVE + 2] = nodeUI.size; colors[idx * ATTRIBUTES_PER_PRIMITIVE + 3] = nodeUI.color; diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index ec11e04..bf5930d 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-s*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=r},{}],3:[function(e,n,t){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n,t){function r(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function v(e){var n=w[e];n.mass=m(e)}function g(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function h(e){var n=w[e];return n||(f(e),n=w[e]),n}function m(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var y=e("ngraph.physics.simulator"),x=y(t),w="function"==typeof Object.create?Object.create(null):{},b={},E=x.settings.springTransform||o;s(),a();var L={step:function(){return x.step()},getNodePosition:function(e){return h(e).pos},setNodePosition:function(e){var n=h(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return x.getBBox()},pinNode:function(e,n){var t=h(e.id);t.isPinned=!!n},isNodePinned:function(e){return h(e.id).isPinned},dispose:function(){n.off("changed",u)},getBody:i,getSpring:r,simulator:x};return L}function o(){}n.exports=r,n.exports.simulator=e("ngraph.physics.simulator")},{"ngraph.physics.simulator":8}],8:[function(e,n,t){function r(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.isPinned||(e.force.reset(),v.updateBodyForce(e),m.update(e));for(n=p.length;n--;)h.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),u=n.createBounds||e("./lib/bounds"),s=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),g=u(l,n),h=f(n),m=s(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return g.update(),en))return l.splice(n,1),0===l.length&&g.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return g.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=r},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":24,"ngraph.quadtreebh":17}],9:[function(e,n,t){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;ut;++t){var s=e[t],f=n/s.mass;s.velocity.x+=f*s.force.x,s.velocity.y+=f*s.force.y;var c=s.velocity.x,d=s.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=r},{}],13:[function(e,n,t){function r(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=r},{}],14:[function(e,n,t){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":24,"ngraph.random":25}],15:[function(e,n,t){function r(e,n,t){var r="[object Array]"===Object.prototype.toString.call(t);if(r)for(var i=0;i0&&u(s.pos,a.pos));if(0===f&&u(s.pos,a.pos))return}c.push(i,s),c.push(i,a)}else{var h=a.pos.x,m=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*h,i.massY=i.massY+a.mass*m;var y=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;if(h>w){y+=1;var L=x;x=w,w+=w-L}if(m>E){y+=2;var P=b;b=E,E+=E-P}var N=r(i,y);N?c.push(N,a):(N=v(),N.left=x,N.top=b,N.right=w,N.bottom=E,N.body=a,o(i,y,N))}}},m=function(e){var n,r,o,i,a=f,u=0,c=0,l=1,p=0,v=1;for(a[0]=g;l;){var h=a[p],m=h.body;l-=1,p+=1;var y=m!==e;m&&y?(r=m.pos.x-e.pos.x,o=m.pos.y-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),n=s*m.mass*e.mass/(i*i*i),u+=n*r,c+=n*o):y&&(r=h.massX/h.mass-e.pos.x,o=h.massY/h.mass-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),(h.right-h.left)/iu&&(t=u),u>o&&(o=u),r>s&&(r=s),s>i&&(i=s)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,p=0,g=v(),g.left=t,g.right=o,g.top=r,g.bottom=i,n=a-1,n>0&&(g.body=e[n]);n--;)h(e[n],g)};return{insertBodies:y,updateBodyForce:m,options:function(e){return e?("number"==typeof e.gravity&&(s=e.gravity),"number"==typeof e.theta&&(d=e.theta),this):{gravity:s,theta:d}}}}},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":25}],18:[function(e,n,t){function r(){this.stack=[],this.popIdx=0}function o(e,n){this.node=e,this.body=n}n.exports=r,r.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new o(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],19:[function(e,n,t){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],20:[function(e,n,t){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],21:[function(e,n,t){function r(e,n,t){var r;n=n||o,t=t||o,r="string"==typeof e?JSON.parse(e):e;var a,u=i();if(void 0===r.links||void 0===r.nodes)throw new Error("Cannot load graph without links and nodes");for(a=0;ae)throw new Error("Invalid number of nodes");var n,t=p();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function o(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=r(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function i(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=p();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function a(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=p();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function u(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=p();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function s(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=p();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function f(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=p();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var u=i*e*n,s=r+o*e+u;r>0&&a.addLink(s,r-1+o*e+u),o>0&&a.addLink(s,r+(o-1)*e+u),i>0&&a.addLink(s,r+o*e+(i-1)*e*n)}return a}function c(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=p(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function d(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=p();for(n=0;e>n;++n)t.addNode(n);return t}function l(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,u=e("ngraph.random").random(o||42),s=p();for(i=0;n>i;++i)s.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,s.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(u.nextDouble()n)return!1;B(),_.splice(n,1);var t=f(e.fromId),r=f(e.toId);return t&&(n=o(e,t.links),n>=0&&t.links.splice(n,1)),r&&(n=o(e,r.links),n>=0&&r.links.splice(n,1)),U(e,"remove"),F(),!0}function h(e,n){var t,r=f(e);if(!r)return null;for(t=0;tn;++n)e(_[n])}function x(e,n,t){var r=f(e);return r&&r.links&&"function"==typeof n?t?b(r.links,e,n):w(r.links,e,n):void 0}function w(e,n,t){for(var r,o=0;o0&&(O.fire("changed",M),M.length=0)}function N(){return Object.keys?k:A}function k(e){if("function"==typeof e)for(var n=Object.keys(j),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function i(e){this.id=e,this.links=[],this.data=null}function a(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=r;var u=e("ngraph.events")},{"ngraph.events":6}],24:[function(e,n,t){function r(e,n){var t;if(e||(e={}),n)for(t in n)if(n.hasOwnProperty(t)){var o=e.hasOwnProperty(t),i=typeof n[t],a=!o||typeof e[t]!==i;a?e[t]=n[t]:"object"===i&&(e[t]=r(e[t],n[t]))}return e}n.exports=r},{}],25:[function(e,n,t){function r(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function o(e,n){var t=n||r();if("function"!=typeof t.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var r,o,i;for(r=e.length-1;r>0;--r)o=t.next(r+1),i=e[o],e[o]=e[r],e[r]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,r,o;for(n=e.length-1;n>0;--n)r=t.next(n+1),o=e[r],e[r]=e[n],e[n]=o;return e}}}n.exports={random:r,randomIterator:o}},{}],26:[function(e,n,t){function r(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=r},{}],27:[function(e,n,t){function r(e,n){var t=o(e);if(void 0===n)return t;for(var r=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},A=function(e){p=!1,o.off("touchmove",k),o.off("touchend",A),o.off("touchcancel",A),c=null,r&&r(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,o.on("touchmove",k),o.on("touchend",A),o.on("touchcancel",A))},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b), -e.removeEventListener("touchstart",_),o.off("mousemove",w),o.off("mouseup",E),o.off("touchmove",k),o.off("touchend",A),o.off("touchcancel",A),P(null)}}}n.exports=r;var o=e("../Utils/documentEvents.js"),i=e("../Utils/browserInfo.js"),a=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":39,"../Utils/documentEvents.js":40,"../Utils/findElementPosition.js":41}],36:[function(e,n,t){function r(e,n){var t=o(n),r=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){r=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(r);var o=i[e.id];return o&&o.onStart&&o.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(r),r=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(r){var t=i[r.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=r;var o=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":57}],37:[function(e,n,t){function r(e,n){function t(e){return d[e]}n=o(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var r=i(n.seed),u=new a(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(e){return{x:r.next(n.maxX),y:r.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"==typeof z?z:!0}function r(){G=G||window.document.body,F=F||i(e,{springLength:80,springCoeff:2e-4}),O=O||a(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||s)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=f(function(){return p()},M)):(X=0,V=0,R=f(p,M)))}function g(){J||(W=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;en,t)})),e.forEachNode(E),T(),e.on("changed",j)}function D(){q=!1,T(),I(),u.off("resize",_),K.off(),R.stop(),e.forEachLink(function(e){n.renderLinks&&b(e)}),e.forEachNode(function(e){L(e),x(e)}),F.dispose(),N()}var M=30;n=n||{};var U,R,B,F=n.layout,O=n.graphics,G=n.container,z=void 0!==n.interactive?n.interactive:!0,q=!1,Y=!0,X=0,V=0,W=!1,H=!1,J=!1,$={offsetX:0,offsetY:0,scale:1},K=o({});return{run:function(e){return q||(r(),h(),P(),m(),S(),q=!0),v(e),this},reset:function(){O.resetScale(),m(),$.scale=1},pause:function(){J=!0,R.stop()},resume:function(){J=!1,R.restart()},rerender:function(){return l(),this},zoomOut:function(){return C(!0)},zoomIn:function(){return C(!1)},moveTo:function(e,n){O.graphCenterChanged($.offsetX-e*$.scale,$.offsetY-n*$.scale),l()},getGraphics:function(){return O},dispose:function(){D()},on:function(e,n){return K.on(e,n),this},off:function(e,n){return K.off(e,n),this}}}n.exports=r;var o=e("ngraph.events"),i=e("ngraph.forcelayout"),a=e("./svgGraphics.js"),u=e("../Utils/windowEvents.js"),s=e("../Input/domInputManager.js"),f=e("../Utils/timer.js"),c=e("../Utils/getDimensions.js"),d=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":34,"../Input/dragndrop.js":35,"../Utils/getDimensions.js":42,"../Utils/timer.js":46,"../Utils/windowEvents.js":47,"./svgGraphics.js":49,"ngraph.events":6,"ngraph.forcelayout":7}],49:[function(e,n,t){function r(){function e(){var e=o("svg");return n=o("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,r,u=0,s=0,f=1,c={},d={},l=function(e){return o("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(e){return o("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+u+","+s+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){u=e,s=n,w()},inputManager:a,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),a=n.getCTM().multiply(i);f=a.a,u=a.e,s=a.f;var c="matrix("+a.a+", 0, 0,"+a.d+","+a.e+","+a.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof r&&r(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):r=e),t},getSvgRoot:function(){return t}};return i(b),b}n.exports=r;var o=e("simplesvg"),i=e("ngraph.events"),a=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":34,"ngraph.events":6,simplesvg:27}],50:[function(e,n,t){function r(e){e=c(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,r,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=i(),P=a(),N=function(e){return u()},k=function(e){return s(3014898687)},A=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),r&&r.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(k=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:o,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,A()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],A()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,A(),I(this),y[0]},resetScale:function(){return j(),r&&(_(),A()),this},init:function(o){var i={};if(e.preserveDrawingBuffer&&(i.preserveDrawingBuffer=!0),n=o,_(),j(),n.appendChild(t),r=t.getContext("experimental-webgl",i),!r){var a="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(a),a}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var u=e.clearColorValue;r.clearColor(u.r,u.g,u.b,u.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}L.load(r),L.updateSize(d/2,l/2),P.load(r),P.updateSize(d/2,l/2),A(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=-t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!r&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!r&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x=e.x*(d/2),e.y=e.y*(-l/2),e},transformGraphToClientCoordinates:function(e){return e.x=e.x/(d/2),e.y=e.y/(-l/2),e.x=e.x*y[0]+y[12],e.y=e.y*y[5]+y[13],e.x=(e.x+1)*d/2,e.y=(1-e.y)*l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return f(T),T}n.exports=r;var o=e("../Input/webglInputManager.js"),i=e("../WebGL/webglLinkProgram.js"),a=e("../WebGL/webglNodeProgram.js"),u=e("../WebGL/webglSquare.js"),s=e("../WebGL/webglLine.js"),f=e("ngraph.events"),c=e("ngraph.merge")},{"../Input/webglInputManager.js":36,"../WebGL/webglLine.js":58,"../WebGL/webglLinkProgram.js":59,"../WebGL/webglNodeProgram.js":60,"../WebGL/webglSquare.js":61,"ngraph.events":6,"ngraph.merge":24}],51:[function(e,n,t){function r(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=r},{}],52:[function(e,n,t){function r(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=r},{}],53:[function(e,n,t){function r(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function r(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function i(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=r},{}],54:[function(e,n,t){function r(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!o(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:r,getCoordinates:a,load:u};return E}function o(e){return 0===(e&e-1)}var i=e("./texture.js");n.exports=r},{"./texture.js":52}],55:[function(e,n,t){function r(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=r},{}],56:[function(e,n,t){function r(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=o(),k=i(),A=1024,j=0,_=new Float32Array(64);return{load:t,position:r,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function o(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function i(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var a=e("./webglAtlas.js"),u=e("./webgl.js");n.exports=r},{"./webgl.js":53,"./webglAtlas.js":54}],57:[function(e,n,t){function r(e){function n(){x=null}function t(e){x=e}function r(e){return"function"==typeof e&&k.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(k,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],k=[],A=e.getGraphicsRoot();h(A);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:r,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var o=e("../Utils/documentEvents.js");n.exports=r},{"../Utils/documentEvents.js":40}],58:[function(e,n,t){function r(e){return{color:o(e)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],59:[function(e,n,t){function r(){var e,n,t,r,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,r=o(a),e=r.createProgram(v,p),n.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&r.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&r.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],60:[function(e,n,t){function r(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=o(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function r(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(N,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:r,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],61:[function(e,n,t){function r(e,n){return{size:"number"==typeof e?e:10,color:o(n)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],62:[function(e,n,t){n.exports="0.7.13"},{}]},{},[1])(1)}); \ No newline at end of file +e.removeEventListener("touchstart",_),o.off("mousemove",w),o.off("mouseup",E),o.off("touchmove",k),o.off("touchend",A),o.off("touchcancel",A),P(null)}}}n.exports=r;var o=e("../Utils/documentEvents.js"),i=e("../Utils/browserInfo.js"),a=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":39,"../Utils/documentEvents.js":40,"../Utils/findElementPosition.js":41}],36:[function(e,n,t){function r(e,n){var t=o(n),r=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){r=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(r);var o=i[e.id];return o&&o.onStart&&o.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(r),r=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(r){var t=i[r.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=r;var o=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":57}],37:[function(e,n,t){function r(e,n){function t(e){return d[e]}n=o(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var r=i(n.seed),u=new a(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(e){return{x:r.next(n.maxX),y:r.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"==typeof z?z:!0}function r(){G=G||window.document.body,F=F||i(e,{springLength:80,springCoeff:2e-4}),O=O||a(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||s)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=f(function(){return p()},M)):(X=0,V=0,R=f(p,M)))}function g(){J||(W=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;en,t)})),e.forEachNode(E),T(),e.on("changed",j)}function D(){q=!1,T(),I(),u.off("resize",_),K.off(),R.stop(),e.forEachLink(function(e){n.renderLinks&&b(e)}),e.forEachNode(function(e){L(e),x(e)}),F.dispose(),N()}var M=30;n=n||{};var U,R,B,F=n.layout,O=n.graphics,G=n.container,z=void 0!==n.interactive?n.interactive:!0,q=!1,Y=!0,X=0,V=0,W=!1,H=!1,J=!1,$={offsetX:0,offsetY:0,scale:1},K=o({});return{run:function(e){return q||(r(),h(),P(),m(),S(),q=!0),v(e),this},reset:function(){O.resetScale(),m(),$.scale=1},pause:function(){J=!0,R.stop()},resume:function(){J=!1,R.restart()},rerender:function(){return l(),this},zoomOut:function(){return C(!0)},zoomIn:function(){return C(!1)},moveTo:function(e,n){O.graphCenterChanged($.offsetX-e*$.scale,$.offsetY-n*$.scale),l()},getGraphics:function(){return O},dispose:function(){D()},on:function(e,n){return K.on(e,n),this},off:function(e,n){return K.off(e,n),this}}}n.exports=r;var o=e("ngraph.events"),i=e("ngraph.forcelayout"),a=e("./svgGraphics.js"),u=e("../Utils/windowEvents.js"),s=e("../Input/domInputManager.js"),f=e("../Utils/timer.js"),c=e("../Utils/getDimensions.js"),d=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":34,"../Input/dragndrop.js":35,"../Utils/getDimensions.js":42,"../Utils/timer.js":46,"../Utils/windowEvents.js":47,"./svgGraphics.js":49,"ngraph.events":6,"ngraph.forcelayout":7}],49:[function(e,n,t){function r(){function e(){var e=o("svg");return n=o("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,r,u=0,s=0,f=1,c={},d={},l=function(e){return o("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(e){return o("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+u+","+s+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){u=e,s=n,w()},inputManager:a,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),a=n.getCTM().multiply(i);f=a.a,u=a.e,s=a.f;var c="matrix("+a.a+", 0, 0,"+a.d+","+a.e+","+a.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof r&&r(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):r=e),t},getSvgRoot:function(){return t}};return i(b),b}n.exports=r;var o=e("simplesvg"),i=e("ngraph.events"),a=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":34,"ngraph.events":6,simplesvg:27}],50:[function(e,n,t){function r(e){e=c(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,r,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=i(),P=a(),N=function(e){return u()},k=function(e){return s(3014898687)},A=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),r&&r.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(k=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:o,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,A()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],A()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,A(),I(this),y[0]},resetScale:function(){return j(),r&&(_(),A()),this},init:function(o){var i={};if(e.preserveDrawingBuffer&&(i.preserveDrawingBuffer=!0),n=o,_(),j(),n.appendChild(t),r=t.getContext("experimental-webgl",i),!r){var a="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(a),a}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var u=e.clearColorValue;r.clearColor(u.r,u.g,u.b,u.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}L.load(r),L.updateSize(d/2,l/2),P.load(r),P.updateSize(d/2,l/2),A(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!r&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!r&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x=e.x*(d/2),e.y=e.y*(-l/2),e},transformGraphToClientCoordinates:function(e){return e.x=e.x/(d/2),e.y=e.y/(-l/2),e.x=e.x*y[0]+y[12],e.y=e.y*y[5]+y[13],e.x=(e.x+1)*d/2,e.y=(1-e.y)*l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return f(T),T}n.exports=r;var o=e("../Input/webglInputManager.js"),i=e("../WebGL/webglLinkProgram.js"),a=e("../WebGL/webglNodeProgram.js"),u=e("../WebGL/webglSquare.js"),s=e("../WebGL/webglLine.js"),f=e("ngraph.events"),c=e("ngraph.merge")},{"../Input/webglInputManager.js":36,"../WebGL/webglLine.js":58,"../WebGL/webglLinkProgram.js":59,"../WebGL/webglNodeProgram.js":60,"../WebGL/webglSquare.js":61,"ngraph.events":6,"ngraph.merge":24}],51:[function(e,n,t){function r(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=r},{}],52:[function(e,n,t){function r(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=r},{}],53:[function(e,n,t){function r(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function r(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function i(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=r},{}],54:[function(e,n,t){function r(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!o(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:r,getCoordinates:a,load:u};return E}function o(e){return 0===(e&e-1)}var i=e("./texture.js");n.exports=r},{"./texture.js":52}],55:[function(e,n,t){function r(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=r},{}],56:[function(e,n,t){function r(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=o(),k=i(),A=1024,j=0,_=new Float32Array(64);return{load:t,position:r,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function o(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function i(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var a=e("./webglAtlas.js"),u=e("./webgl.js");n.exports=r},{"./webgl.js":53,"./webglAtlas.js":54}],57:[function(e,n,t){function r(e){function n(){x=null}function t(e){x=e}function r(e){return"function"==typeof e&&k.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(k,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],k=[],A=e.getGraphicsRoot();h(A);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:r,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var o=e("../Utils/documentEvents.js");n.exports=r},{"../Utils/documentEvents.js":40}],58:[function(e,n,t){function r(e){return{color:o(e)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],59:[function(e,n,t){function r(){var e,n,t,r,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,r=o(a),e=r.createProgram(v,p),n.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&r.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&r.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],60:[function(e,n,t){function r(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=o(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=-n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function r(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(N,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:r,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],61:[function(e,n,t){function r(e,n){return{size:"number"==typeof e?e:10,color:o(n)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],62:[function(e,n,t){n.exports="0.7.13"},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/src/View/webglGraphics.js b/src/View/webglGraphics.js index 5c9ad58..7a2fd4f 100644 --- a/src/View/webglGraphics.js +++ b/src/View/webglGraphics.js @@ -426,7 +426,7 @@ function webglGraphics(options) { for (var i = 0; i < nodesCount; ++i) { var ui = nodes[i]; pos.x = ui.position.x; - pos.y = -ui.position.y; + pos.y = ui.position.y; if (userPlaceNodeCallback) { userPlaceNodeCallback(ui, pos); } diff --git a/src/WebGL/webglNodeProgram.js b/src/WebGL/webglNodeProgram.js index 70e2d2d..402cb48 100644 --- a/src/WebGL/webglNodeProgram.js +++ b/src/WebGL/webglNodeProgram.js @@ -109,7 +109,7 @@ function webglNodeProgram() { var idx = nodeUI.id; positions[idx * ATTRIBUTES_PER_PRIMITIVE] = pos.x; - positions[idx * ATTRIBUTES_PER_PRIMITIVE + 1] = pos.y; + positions[idx * ATTRIBUTES_PER_PRIMITIVE + 1] = -pos.y; positions[idx * ATTRIBUTES_PER_PRIMITIVE + 2] = nodeUI.size; colors[idx * ATTRIBUTES_PER_PRIMITIVE + 3] = nodeUI.color; From 2342b467062e08582af1a101bd878b0733af4772 Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 9 Sep 2015 23:49:53 -0700 Subject: [PATCH 214/276] Year update --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index a1d90bf..4371805 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2011 - 2014, Andrei Kashcha +Copyright (c) 2011 - 2015, Andrei Kashcha All rights reserved. Redistribution and use in source and binary forms, with or without From 58584963558bc3caba2169656e2c1738e43709ad Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 9 Sep 2015 23:50:26 -0700 Subject: [PATCH 215/276] Using spdx license name, added `release` script --- package.json | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index c99e7a2..a92f06f 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,8 @@ }, "scripts": { "start": "gulp", - "test": "tap test/*.js" + "test": "tap test/*.js", + "release": "gulp release" }, "repository": { "type": "git", @@ -18,18 +19,18 @@ "graph" ], "author": "Andrei Kashcha", - "license": "BSD", + "license": "BSD-3-Clause", "devDependencies": { "browserify": "^8.0.3", "del": "^1.1.1", - "gulp": "^3.8.10", + "gulp": "^3.9.0", "gulp-rename": "^1.2.0", - "gulp-uglify": "^1.0.2", "gulp-run": "^1.6.5", + "gulp-uglify": "^1.0.2", "gulp-util": "^3.0.2", + "tap": "^0.4.13", "vinyl-buffer": "^1.0.0", - "vinyl-source-stream": "^1.0.0", - "tap": "^0.4.13" + "vinyl-source-stream": "^1.0.0" }, "dependencies": { "gintersect": "0.1.0", From 69ec53d1b6faffbde0d0ac17a6eb8888495cfdfb Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 9 Sep 2015 23:52:03 -0700 Subject: [PATCH 216/276] Version update Fixes in webgl shaders API require version bump --- CHANGELOG | 9 +++++++++ dist/vivagraph.js | 2 +- dist/vivagraph.min.js | 2 +- src/version.js | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index e08f98c..5674eed 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,12 @@ +v0.8.1 + date Sep 9, 2015 + - Improved layout performance in some cases + - Extended WebGL API to transform from/to webgl coordinates space + - Custom shaders now receive layout's view of node position. This means + that `y` coordinate needs to be replaced to `-y` in your custom shaders + code + - Bug fixes + - Documentation updates v0.7.7 date Mar 24, 2015 - Upgraded to latest `ngraph` modules diff --git a/dist/vivagraph.js b/dist/vivagraph.js index cff3af6..f4003f2 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -6838,7 +6838,7 @@ function webglSquare(size, color) { },{"./parseColor.js":51}],62:[function(require,module,exports){ // todo: this should be generated at build time. -module.exports = '0.7.13'; +module.exports = '0.8.1'; },{}]},{},[1])(1) }); \ No newline at end of file diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index bf5930d..8ec782d 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-s*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=r},{}],3:[function(e,n,t){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n,t){function r(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function v(e){var n=w[e];n.mass=m(e)}function g(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function h(e){var n=w[e];return n||(f(e),n=w[e]),n}function m(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var y=e("ngraph.physics.simulator"),x=y(t),w="function"==typeof Object.create?Object.create(null):{},b={},E=x.settings.springTransform||o;s(),a();var L={step:function(){return x.step()},getNodePosition:function(e){return h(e).pos},setNodePosition:function(e){var n=h(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return x.getBBox()},pinNode:function(e,n){var t=h(e.id);t.isPinned=!!n},isNodePinned:function(e){return h(e.id).isPinned},dispose:function(){n.off("changed",u)},getBody:i,getSpring:r,simulator:x};return L}function o(){}n.exports=r,n.exports.simulator=e("ngraph.physics.simulator")},{"ngraph.physics.simulator":8}],8:[function(e,n,t){function r(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.isPinned||(e.force.reset(),v.updateBodyForce(e),m.update(e));for(n=p.length;n--;)h.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),u=n.createBounds||e("./lib/bounds"),s=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),g=u(l,n),h=f(n),m=s(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return g.update(),en))return l.splice(n,1),0===l.length&&g.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return g.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=r},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":24,"ngraph.quadtreebh":17}],9:[function(e,n,t){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;ut;++t){var s=e[t],f=n/s.mass;s.velocity.x+=f*s.force.x,s.velocity.y+=f*s.force.y;var c=s.velocity.x,d=s.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=r},{}],13:[function(e,n,t){function r(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=r},{}],14:[function(e,n,t){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":24,"ngraph.random":25}],15:[function(e,n,t){function r(e,n,t){var r="[object Array]"===Object.prototype.toString.call(t);if(r)for(var i=0;i0&&u(s.pos,a.pos));if(0===f&&u(s.pos,a.pos))return}c.push(i,s),c.push(i,a)}else{var h=a.pos.x,m=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*h,i.massY=i.massY+a.mass*m;var y=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;if(h>w){y+=1;var L=x;x=w,w+=w-L}if(m>E){y+=2;var P=b;b=E,E+=E-P}var N=r(i,y);N?c.push(N,a):(N=v(),N.left=x,N.top=b,N.right=w,N.bottom=E,N.body=a,o(i,y,N))}}},m=function(e){var n,r,o,i,a=f,u=0,c=0,l=1,p=0,v=1;for(a[0]=g;l;){var h=a[p],m=h.body;l-=1,p+=1;var y=m!==e;m&&y?(r=m.pos.x-e.pos.x,o=m.pos.y-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),n=s*m.mass*e.mass/(i*i*i),u+=n*r,c+=n*o):y&&(r=h.massX/h.mass-e.pos.x,o=h.massY/h.mass-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),(h.right-h.left)/iu&&(t=u),u>o&&(o=u),r>s&&(r=s),s>i&&(i=s)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,p=0,g=v(),g.left=t,g.right=o,g.top=r,g.bottom=i,n=a-1,n>0&&(g.body=e[n]);n--;)h(e[n],g)};return{insertBodies:y,updateBodyForce:m,options:function(e){return e?("number"==typeof e.gravity&&(s=e.gravity),"number"==typeof e.theta&&(d=e.theta),this):{gravity:s,theta:d}}}}},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":25}],18:[function(e,n,t){function r(){this.stack=[],this.popIdx=0}function o(e,n){this.node=e,this.body=n}n.exports=r,r.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new o(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],19:[function(e,n,t){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],20:[function(e,n,t){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],21:[function(e,n,t){function r(e,n,t){var r;n=n||o,t=t||o,r="string"==typeof e?JSON.parse(e):e;var a,u=i();if(void 0===r.links||void 0===r.nodes)throw new Error("Cannot load graph without links and nodes");for(a=0;ae)throw new Error("Invalid number of nodes");var n,t=p();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function o(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=r(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function i(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=p();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function a(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=p();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function u(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=p();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function s(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=p();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function f(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=p();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var u=i*e*n,s=r+o*e+u;r>0&&a.addLink(s,r-1+o*e+u),o>0&&a.addLink(s,r+(o-1)*e+u),i>0&&a.addLink(s,r+o*e+(i-1)*e*n)}return a}function c(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=p(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function d(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=p();for(n=0;e>n;++n)t.addNode(n);return t}function l(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,u=e("ngraph.random").random(o||42),s=p();for(i=0;n>i;++i)s.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,s.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(u.nextDouble()n)return!1;B(),_.splice(n,1);var t=f(e.fromId),r=f(e.toId);return t&&(n=o(e,t.links),n>=0&&t.links.splice(n,1)),r&&(n=o(e,r.links),n>=0&&r.links.splice(n,1)),U(e,"remove"),F(),!0}function h(e,n){var t,r=f(e);if(!r)return null;for(t=0;tn;++n)e(_[n])}function x(e,n,t){var r=f(e);return r&&r.links&&"function"==typeof n?t?b(r.links,e,n):w(r.links,e,n):void 0}function w(e,n,t){for(var r,o=0;o0&&(O.fire("changed",M),M.length=0)}function N(){return Object.keys?k:A}function k(e){if("function"==typeof e)for(var n=Object.keys(j),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function i(e){this.id=e,this.links=[],this.data=null}function a(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=r;var u=e("ngraph.events")},{"ngraph.events":6}],24:[function(e,n,t){function r(e,n){var t;if(e||(e={}),n)for(t in n)if(n.hasOwnProperty(t)){var o=e.hasOwnProperty(t),i=typeof n[t],a=!o||typeof e[t]!==i;a?e[t]=n[t]:"object"===i&&(e[t]=r(e[t],n[t]))}return e}n.exports=r},{}],25:[function(e,n,t){function r(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function o(e,n){var t=n||r();if("function"!=typeof t.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var r,o,i;for(r=e.length-1;r>0;--r)o=t.next(r+1),i=e[o],e[o]=e[r],e[r]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,r,o;for(n=e.length-1;n>0;--n)r=t.next(n+1),o=e[r],e[r]=e[n],e[n]=o;return e}}}n.exports={random:r,randomIterator:o}},{}],26:[function(e,n,t){function r(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=r},{}],27:[function(e,n,t){function r(e,n){var t=o(e);if(void 0===n)return t;for(var r=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},A=function(e){p=!1,o.off("touchmove",k),o.off("touchend",A),o.off("touchcancel",A),c=null,r&&r(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,o.on("touchmove",k),o.on("touchend",A),o.on("touchcancel",A))},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b), -e.removeEventListener("touchstart",_),o.off("mousemove",w),o.off("mouseup",E),o.off("touchmove",k),o.off("touchend",A),o.off("touchcancel",A),P(null)}}}n.exports=r;var o=e("../Utils/documentEvents.js"),i=e("../Utils/browserInfo.js"),a=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":39,"../Utils/documentEvents.js":40,"../Utils/findElementPosition.js":41}],36:[function(e,n,t){function r(e,n){var t=o(n),r=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){r=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(r);var o=i[e.id];return o&&o.onStart&&o.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(r),r=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(r){var t=i[r.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=r;var o=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":57}],37:[function(e,n,t){function r(e,n){function t(e){return d[e]}n=o(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var r=i(n.seed),u=new a(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(e){return{x:r.next(n.maxX),y:r.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"==typeof z?z:!0}function r(){G=G||window.document.body,F=F||i(e,{springLength:80,springCoeff:2e-4}),O=O||a(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||s)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=f(function(){return p()},M)):(X=0,V=0,R=f(p,M)))}function g(){J||(W=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;en,t)})),e.forEachNode(E),T(),e.on("changed",j)}function D(){q=!1,T(),I(),u.off("resize",_),K.off(),R.stop(),e.forEachLink(function(e){n.renderLinks&&b(e)}),e.forEachNode(function(e){L(e),x(e)}),F.dispose(),N()}var M=30;n=n||{};var U,R,B,F=n.layout,O=n.graphics,G=n.container,z=void 0!==n.interactive?n.interactive:!0,q=!1,Y=!0,X=0,V=0,W=!1,H=!1,J=!1,$={offsetX:0,offsetY:0,scale:1},K=o({});return{run:function(e){return q||(r(),h(),P(),m(),S(),q=!0),v(e),this},reset:function(){O.resetScale(),m(),$.scale=1},pause:function(){J=!0,R.stop()},resume:function(){J=!1,R.restart()},rerender:function(){return l(),this},zoomOut:function(){return C(!0)},zoomIn:function(){return C(!1)},moveTo:function(e,n){O.graphCenterChanged($.offsetX-e*$.scale,$.offsetY-n*$.scale),l()},getGraphics:function(){return O},dispose:function(){D()},on:function(e,n){return K.on(e,n),this},off:function(e,n){return K.off(e,n),this}}}n.exports=r;var o=e("ngraph.events"),i=e("ngraph.forcelayout"),a=e("./svgGraphics.js"),u=e("../Utils/windowEvents.js"),s=e("../Input/domInputManager.js"),f=e("../Utils/timer.js"),c=e("../Utils/getDimensions.js"),d=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":34,"../Input/dragndrop.js":35,"../Utils/getDimensions.js":42,"../Utils/timer.js":46,"../Utils/windowEvents.js":47,"./svgGraphics.js":49,"ngraph.events":6,"ngraph.forcelayout":7}],49:[function(e,n,t){function r(){function e(){var e=o("svg");return n=o("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,r,u=0,s=0,f=1,c={},d={},l=function(e){return o("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(e){return o("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+u+","+s+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){u=e,s=n,w()},inputManager:a,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),a=n.getCTM().multiply(i);f=a.a,u=a.e,s=a.f;var c="matrix("+a.a+", 0, 0,"+a.d+","+a.e+","+a.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof r&&r(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):r=e),t},getSvgRoot:function(){return t}};return i(b),b}n.exports=r;var o=e("simplesvg"),i=e("ngraph.events"),a=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":34,"ngraph.events":6,simplesvg:27}],50:[function(e,n,t){function r(e){e=c(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,r,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=i(),P=a(),N=function(e){return u()},k=function(e){return s(3014898687)},A=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),r&&r.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(k=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:o,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,A()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],A()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,A(),I(this),y[0]},resetScale:function(){return j(),r&&(_(),A()),this},init:function(o){var i={};if(e.preserveDrawingBuffer&&(i.preserveDrawingBuffer=!0),n=o,_(),j(),n.appendChild(t),r=t.getContext("experimental-webgl",i),!r){var a="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(a),a}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var u=e.clearColorValue;r.clearColor(u.r,u.g,u.b,u.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}L.load(r),L.updateSize(d/2,l/2),P.load(r),P.updateSize(d/2,l/2),A(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!r&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!r&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x=e.x*(d/2),e.y=e.y*(-l/2),e},transformGraphToClientCoordinates:function(e){return e.x=e.x/(d/2),e.y=e.y/(-l/2),e.x=e.x*y[0]+y[12],e.y=e.y*y[5]+y[13],e.x=(e.x+1)*d/2,e.y=(1-e.y)*l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return f(T),T}n.exports=r;var o=e("../Input/webglInputManager.js"),i=e("../WebGL/webglLinkProgram.js"),a=e("../WebGL/webglNodeProgram.js"),u=e("../WebGL/webglSquare.js"),s=e("../WebGL/webglLine.js"),f=e("ngraph.events"),c=e("ngraph.merge")},{"../Input/webglInputManager.js":36,"../WebGL/webglLine.js":58,"../WebGL/webglLinkProgram.js":59,"../WebGL/webglNodeProgram.js":60,"../WebGL/webglSquare.js":61,"ngraph.events":6,"ngraph.merge":24}],51:[function(e,n,t){function r(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=r},{}],52:[function(e,n,t){function r(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=r},{}],53:[function(e,n,t){function r(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function r(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function i(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=r},{}],54:[function(e,n,t){function r(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!o(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:r,getCoordinates:a,load:u};return E}function o(e){return 0===(e&e-1)}var i=e("./texture.js");n.exports=r},{"./texture.js":52}],55:[function(e,n,t){function r(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=r},{}],56:[function(e,n,t){function r(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=o(),k=i(),A=1024,j=0,_=new Float32Array(64);return{load:t,position:r,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function o(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function i(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var a=e("./webglAtlas.js"),u=e("./webgl.js");n.exports=r},{"./webgl.js":53,"./webglAtlas.js":54}],57:[function(e,n,t){function r(e){function n(){x=null}function t(e){x=e}function r(e){return"function"==typeof e&&k.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(k,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],k=[],A=e.getGraphicsRoot();h(A);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:r,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var o=e("../Utils/documentEvents.js");n.exports=r},{"../Utils/documentEvents.js":40}],58:[function(e,n,t){function r(e){return{color:o(e)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],59:[function(e,n,t){function r(){var e,n,t,r,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,r=o(a),e=r.createProgram(v,p),n.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&r.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&r.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],60:[function(e,n,t){function r(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=o(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=-n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function r(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(N,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:r,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],61:[function(e,n,t){function r(e,n){return{size:"number"==typeof e?e:10,color:o(n)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],62:[function(e,n,t){n.exports="0.7.13"},{}]},{},[1])(1)}); \ No newline at end of file +e.removeEventListener("touchstart",_),o.off("mousemove",w),o.off("mouseup",E),o.off("touchmove",k),o.off("touchend",A),o.off("touchcancel",A),P(null)}}}n.exports=r;var o=e("../Utils/documentEvents.js"),i=e("../Utils/browserInfo.js"),a=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":39,"../Utils/documentEvents.js":40,"../Utils/findElementPosition.js":41}],36:[function(e,n,t){function r(e,n){var t=o(n),r=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){r=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(r);var o=i[e.id];return o&&o.onStart&&o.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(r),r=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(r){var t=i[r.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=r;var o=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":57}],37:[function(e,n,t){function r(e,n){function t(e){return d[e]}n=o(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var r=i(n.seed),u=new a(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(e){return{x:r.next(n.maxX),y:r.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"==typeof z?z:!0}function r(){G=G||window.document.body,F=F||i(e,{springLength:80,springCoeff:2e-4}),O=O||a(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||s)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=f(function(){return p()},M)):(X=0,V=0,R=f(p,M)))}function g(){J||(W=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;en,t)})),e.forEachNode(E),T(),e.on("changed",j)}function D(){q=!1,T(),I(),u.off("resize",_),K.off(),R.stop(),e.forEachLink(function(e){n.renderLinks&&b(e)}),e.forEachNode(function(e){L(e),x(e)}),F.dispose(),N()}var M=30;n=n||{};var U,R,B,F=n.layout,O=n.graphics,G=n.container,z=void 0!==n.interactive?n.interactive:!0,q=!1,Y=!0,X=0,V=0,W=!1,H=!1,J=!1,$={offsetX:0,offsetY:0,scale:1},K=o({});return{run:function(e){return q||(r(),h(),P(),m(),S(),q=!0),v(e),this},reset:function(){O.resetScale(),m(),$.scale=1},pause:function(){J=!0,R.stop()},resume:function(){J=!1,R.restart()},rerender:function(){return l(),this},zoomOut:function(){return C(!0)},zoomIn:function(){return C(!1)},moveTo:function(e,n){O.graphCenterChanged($.offsetX-e*$.scale,$.offsetY-n*$.scale),l()},getGraphics:function(){return O},dispose:function(){D()},on:function(e,n){return K.on(e,n),this},off:function(e,n){return K.off(e,n),this}}}n.exports=r;var o=e("ngraph.events"),i=e("ngraph.forcelayout"),a=e("./svgGraphics.js"),u=e("../Utils/windowEvents.js"),s=e("../Input/domInputManager.js"),f=e("../Utils/timer.js"),c=e("../Utils/getDimensions.js"),d=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":34,"../Input/dragndrop.js":35,"../Utils/getDimensions.js":42,"../Utils/timer.js":46,"../Utils/windowEvents.js":47,"./svgGraphics.js":49,"ngraph.events":6,"ngraph.forcelayout":7}],49:[function(e,n,t){function r(){function e(){var e=o("svg");return n=o("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,r,u=0,s=0,f=1,c={},d={},l=function(e){return o("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(e){return o("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+u+","+s+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){u=e,s=n,w()},inputManager:a,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),a=n.getCTM().multiply(i);f=a.a,u=a.e,s=a.f;var c="matrix("+a.a+", 0, 0,"+a.d+","+a.e+","+a.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof r&&r(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):r=e),t},getSvgRoot:function(){return t}};return i(b),b}n.exports=r;var o=e("simplesvg"),i=e("ngraph.events"),a=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":34,"ngraph.events":6,simplesvg:27}],50:[function(e,n,t){function r(e){e=c(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,r,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=i(),P=a(),N=function(e){return u()},k=function(e){return s(3014898687)},A=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),r&&r.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(k=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:o,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,A()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],A()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,A(),I(this),y[0]},resetScale:function(){return j(),r&&(_(),A()),this},init:function(o){var i={};if(e.preserveDrawingBuffer&&(i.preserveDrawingBuffer=!0),n=o,_(),j(),n.appendChild(t),r=t.getContext("experimental-webgl",i),!r){var a="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(a),a}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var u=e.clearColorValue;r.clearColor(u.r,u.g,u.b,u.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}L.load(r),L.updateSize(d/2,l/2),P.load(r),P.updateSize(d/2,l/2),A(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!r&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!r&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x=e.x*(d/2),e.y=e.y*(-l/2),e},transformGraphToClientCoordinates:function(e){return e.x=e.x/(d/2),e.y=e.y/(-l/2),e.x=e.x*y[0]+y[12],e.y=e.y*y[5]+y[13],e.x=(e.x+1)*d/2,e.y=(1-e.y)*l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return f(T),T}n.exports=r;var o=e("../Input/webglInputManager.js"),i=e("../WebGL/webglLinkProgram.js"),a=e("../WebGL/webglNodeProgram.js"),u=e("../WebGL/webglSquare.js"),s=e("../WebGL/webglLine.js"),f=e("ngraph.events"),c=e("ngraph.merge")},{"../Input/webglInputManager.js":36,"../WebGL/webglLine.js":58,"../WebGL/webglLinkProgram.js":59,"../WebGL/webglNodeProgram.js":60,"../WebGL/webglSquare.js":61,"ngraph.events":6,"ngraph.merge":24}],51:[function(e,n,t){function r(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=r},{}],52:[function(e,n,t){function r(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=r},{}],53:[function(e,n,t){function r(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function r(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function i(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=r},{}],54:[function(e,n,t){function r(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!o(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:r,getCoordinates:a,load:u};return E}function o(e){return 0===(e&e-1)}var i=e("./texture.js");n.exports=r},{"./texture.js":52}],55:[function(e,n,t){function r(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=r},{}],56:[function(e,n,t){function r(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=o(),k=i(),A=1024,j=0,_=new Float32Array(64);return{load:t,position:r,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function o(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function i(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var a=e("./webglAtlas.js"),u=e("./webgl.js");n.exports=r},{"./webgl.js":53,"./webglAtlas.js":54}],57:[function(e,n,t){function r(e){function n(){x=null}function t(e){x=e}function r(e){return"function"==typeof e&&k.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(k,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],k=[],A=e.getGraphicsRoot();h(A);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:r,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var o=e("../Utils/documentEvents.js");n.exports=r},{"../Utils/documentEvents.js":40}],58:[function(e,n,t){function r(e){return{color:o(e)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],59:[function(e,n,t){function r(){var e,n,t,r,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,r=o(a),e=r.createProgram(v,p),n.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&r.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&r.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],60:[function(e,n,t){function r(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=o(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=-n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function r(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(N,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:r,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],61:[function(e,n,t){function r(e,n){return{size:"number"==typeof e?e:10,color:o(n)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],62:[function(e,n,t){n.exports="0.8.1"},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/src/version.js b/src/version.js index c6bd126..d55dbb2 100644 --- a/src/version.js +++ b/src/version.js @@ -1,2 +1,2 @@ // todo: this should be generated at build time. -module.exports = '0.7.13'; +module.exports = '0.8.1'; From 22266543c50e6236656853683b5b5172e562c444 Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 9 Sep 2015 23:52:22 -0700 Subject: [PATCH 217/276] 0.8.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a92f06f..ce90d0e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.7.12", + "version": "0.8.1", "description": "Graph Drawing Library", "main": "src/viva", "directories": { From 4d8aa349d69cc874900fc61b6d1e9feb64a1cebe Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 23 Sep 2015 22:34:46 -0700 Subject: [PATCH 218/276] Use lastFound node as well at mouseUp --- src/WebGL/webglInputEvents.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/WebGL/webglInputEvents.js b/src/WebGL/webglInputEvents.js index a24457f..a4654f1 100644 --- a/src/WebGL/webglInputEvents.js +++ b/src/WebGL/webglInputEvents.js @@ -236,11 +236,13 @@ function webglInputEvents(webglGraphics) { pos.x = e.clientX - boundRect.left; pos.y = e.clientY - boundRect.top; - args = [getNodeAtClientPos(pos), e]; + var nodeAtClientPos = getNodeAtClientPos(pos); + var sameNode = nodeAtClientPos === lastFound; + args = [nodeAtClientPos || lastFound, e]; if (args[0]) { window.document.onselectstart = prevSelectStart; - if (clickTime - lastClickTime < 400 && args[0] === lastFound) { + if (clickTime - lastClickTime < 400 && sameNode) { invoke(dblClickCallback, args); } else { invoke(clickCallback, args); From 6a1614d1c73446a0f1dd84a8a9d2f6d5c4ad1aa8 Mon Sep 17 00:00:00 2001 From: Andrei Kashcha Date: Sat, 16 Jan 2016 00:45:29 -0800 Subject: [PATCH 219/276] Removed Facebook demo Facebook deprecated their API and these graphs are no longer fun to explore --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 7a9a173..5c133e7 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,6 @@ Some examples of library usage in the real projects: * [Amazon Visualization](http://www.yasiv.com/amazon#/Search?q=graph%20drawing&category=Books&lang=US) Shows related products on Amazon.com, uses SVG as graph output * [YouTube Visualization](http://www.yasiv.com/youtube#/Search?q=write%20in%20c) Shows related videos from YouTube. SVG based. -* [Facebook Visualization](http://www.yasiv.com/facebook) friendship visualization on Facebook. WebGL based. * [Graph Viewer](http://www.yasiv.com/graphs#Bai/rw496) visualization of sparse matrices collection of the University of Florida. WebGL based. * [Vkontakte Visualization](http://www.yasiv.com/vk) friendship visualization of the largest social network in Russia [vk.com](https://vk.com). WebGL based. From f523ae59f540a69c26aaf9a05ef0197de9f6daad Mon Sep 17 00:00:00 2001 From: anvaka Date: Mon, 1 Feb 2016 21:26:14 -0800 Subject: [PATCH 220/276] Updated years --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 4371805..c713177 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2011 - 2015, Andrei Kashcha +Copyright (c) 2011 - 2016, Andrei Kashcha All rights reserved. Redistribution and use in source and binary forms, with or without From a21c6b56fd5937c29cfe6a74943ab4a2d829b07a Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 30 Mar 2016 18:40:43 -0700 Subject: [PATCH 221/276] Added example with container --- README.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5c133e7..7f031f5 100644 --- a/README.md +++ b/README.md @@ -25,10 +25,23 @@ var renderer = Viva.Graph.View.renderer(graph); renderer.run(); ``` -This will produce the following layout: +This will instantiate a graph inside `document.body`: ![Simple graph](https://github.com/anvaka/VivaGraphJS/raw/master/packages/Images/mingraph.png) +If you want to render graph in your own DOM element: + +```javascript +var graph = Viva.Graph.graph(); +graph.addLink(1, 2); + +// specify where it should be rendered: +var renderer = Viva.Graph.View.renderer(graph, { + container: document.getElementById('graphDiv') +}); +renderer.run(); +``` + The code above adds a link to the graph between nodes `1` and `2`. Since nodes are not yet in the graph they will be created. It's equivalent to From dd5f4aa59b36979b59c93132f4ef0099d82daf45 Mon Sep 17 00:00:00 2001 From: anvaka Date: Tue, 5 Jul 2016 22:43:25 -0700 Subject: [PATCH 222/276] Using d3-force as layout algorithm --- demos/other/d3layout/index.html | 31 +++++++++ demos/other/d3layout/index.js | 117 ++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+) create mode 100644 demos/other/d3layout/index.html create mode 100644 demos/other/d3layout/index.js diff --git a/demos/other/d3layout/index.html b/demos/other/d3layout/index.html new file mode 100644 index 0000000..80982bf --- /dev/null +++ b/demos/other/d3layout/index.html @@ -0,0 +1,31 @@ + + + + + + VivaGraph and d3 layout + + + + + + + + + + + +
+ + + diff --git a/demos/other/d3layout/index.js b/demos/other/d3layout/index.js new file mode 100644 index 0000000..f37d280 --- /dev/null +++ b/demos/other/d3layout/index.js @@ -0,0 +1,117 @@ +var graphGenerator = Viva.Graph.generator(); +var graph = graphGenerator.grid(20, 20); + +var layout = d3Force(graph, { + springLength : 20, + springCoeff : 1, + gravity: -30, + springIterations: 10 +}); + +var graphics = Viva.Graph.View.webglGraphics(); + +var renderer = Viva.Graph.View.renderer(graph, { + layout: layout, + graphics: graphics, + renderLinks: true, + prerender: true +}); + +renderer.run(); + +// TODO: extract into module +function d3Force(graph, options) { + // todo: check input + var nodes = [], links = []; + var nodeIdToIdx = Object.create(null); + var linkIdToD3Link = Object.create(null); + + graph.forEachNode(function(n) { + var index = nodes.length; + nodeIdToIdx[n.id] = index; + var node = { + index: index + } + nodes.push(node); + }); + + graph.forEachLink(function(l) { + var source = nodeIdToIdx[l.fromId]; + var target = nodeIdToIdx[l.toId]; + + var index = links.length; + var link = {source: source, target: target, index: index} + links.push(link); + linkIdToD3Link[l.id] = link; + }); + + var simulation = d3.forceSimulation(nodes) + .force("charge", d3.forceManyBody().strength(options.gravity)) + .force("link", d3.forceLink(links) + .strength(options.springCoeff) + .distance(options.springLength) + .iterations(options.springIterations) + ); + + simulation.stop(); + + return { + step: function() { + simulation.tick(); + }, + + getNodePosition: getNodePosition, + + getLinkPosition: function(linkId) { + var link = linkIdToD3Link[linkId]; + return { + from: link.source, + to: link.target + }; + }, + + getGraphRect: function() { + var minX = Number.POSITIVE_INFINITY; + var minY = Number.POSITIVE_INFINITY; + var maxX = Number.NEGATIVE_INFINITY; + var maxY = Number.NEGATIVE_INFINITY; + + nodes.forEach(function(node) { + if (node.x < minX) minX = node.x; + if (node.x > maxX) maxX = node.x; + + if (node.y < minY) minY = node.y; + if (node.y > maxY) maxY = node.y; + }) + + return { + x1: minX, + x2: maxX, + y1: minY, + y2: maxY + } + }, + + isNodePinned: function() { + // TODO: implement + return false; + }, + + pinNode: function() { + // TODO: implement me + }, + + dispose: function() { + }, + + setNodePosition: function(nodeId, x, y) { + var pos = getNodePosition(nodeId); + pos.x = x; + pos.y = y; + } + } + + function getNodePosition(nodeId) { + return nodes[nodeIdToIdx[nodeId]]; + } +} From 9824a59c2a94db807924ffced01fe43cdb036d86 Mon Sep 17 00:00:00 2001 From: Mathias Rangel Wulff Date: Fri, 9 Sep 2016 21:17:31 +0200 Subject: [PATCH 223/276] Correct check for undefined variable The code was comparing the result of `typeof` with a variable named `undefined` As typeof returns a string it should compare to `'undefined'` --- src/Utils/windowEvents.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Utils/windowEvents.js b/src/Utils/windowEvents.js index f101d06..8f01588 100644 --- a/src/Utils/windowEvents.js +++ b/src/Utils/windowEvents.js @@ -3,7 +3,7 @@ var nullEvents = require('./nullEvents.js'); module.exports = createDocumentEvents(); function createDocumentEvents() { - if (typeof window === undefined) { + if (typeof window === 'undefined') { return nullEvents; } From 5b6c723bf132e23d9f02eed11ba6b7c36ae86144 Mon Sep 17 00:00:00 2001 From: anvaka Date: Fri, 9 Sep 2016 20:27:14 -0700 Subject: [PATCH 224/276] Building for 0.8.2 --- dist/vivagraph.js | 8 +++++--- dist/vivagraph.min.js | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index f4003f2..de13506 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -4125,7 +4125,7 @@ var nullEvents = require('./nullEvents.js'); module.exports = createDocumentEvents(); function createDocumentEvents() { - if (typeof window === undefined) { + if (typeof window === 'undefined') { return nullEvents; } @@ -6447,11 +6447,13 @@ function webglInputEvents(webglGraphics) { pos.x = e.clientX - boundRect.left; pos.y = e.clientY - boundRect.top; - args = [getNodeAtClientPos(pos), e]; + var nodeAtClientPos = getNodeAtClientPos(pos); + var sameNode = nodeAtClientPos === lastFound; + args = [nodeAtClientPos || lastFound, e]; if (args[0]) { window.document.onselectstart = prevSelectStart; - if (clickTime - lastClickTime < 400 && args[0] === lastFound) { + if (clickTime - lastClickTime < 400 && sameNode) { invoke(dblClickCallback, args); } else { invoke(clickCallback, args); diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 8ec782d..ee186a0 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-s*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=r},{}],3:[function(e,n,t){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n,t){function r(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function v(e){var n=w[e];n.mass=m(e)}function g(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function h(e){var n=w[e];return n||(f(e),n=w[e]),n}function m(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var y=e("ngraph.physics.simulator"),x=y(t),w="function"==typeof Object.create?Object.create(null):{},b={},E=x.settings.springTransform||o;s(),a();var L={step:function(){return x.step()},getNodePosition:function(e){return h(e).pos},setNodePosition:function(e){var n=h(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return x.getBBox()},pinNode:function(e,n){var t=h(e.id);t.isPinned=!!n},isNodePinned:function(e){return h(e.id).isPinned},dispose:function(){n.off("changed",u)},getBody:i,getSpring:r,simulator:x};return L}function o(){}n.exports=r,n.exports.simulator=e("ngraph.physics.simulator")},{"ngraph.physics.simulator":8}],8:[function(e,n,t){function r(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.isPinned||(e.force.reset(),v.updateBodyForce(e),m.update(e));for(n=p.length;n--;)h.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),u=n.createBounds||e("./lib/bounds"),s=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),g=u(l,n),h=f(n),m=s(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return g.update(),en))return l.splice(n,1),0===l.length&&g.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return g.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=r},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":24,"ngraph.quadtreebh":17}],9:[function(e,n,t){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;ut;++t){var s=e[t],f=n/s.mass;s.velocity.x+=f*s.force.x,s.velocity.y+=f*s.force.y;var c=s.velocity.x,d=s.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=r},{}],13:[function(e,n,t){function r(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=r},{}],14:[function(e,n,t){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":24,"ngraph.random":25}],15:[function(e,n,t){function r(e,n,t){var r="[object Array]"===Object.prototype.toString.call(t);if(r)for(var i=0;i0&&u(s.pos,a.pos));if(0===f&&u(s.pos,a.pos))return}c.push(i,s),c.push(i,a)}else{var h=a.pos.x,m=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*h,i.massY=i.massY+a.mass*m;var y=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;if(h>w){y+=1;var L=x;x=w,w+=w-L}if(m>E){y+=2;var P=b;b=E,E+=E-P}var N=r(i,y);N?c.push(N,a):(N=v(),N.left=x,N.top=b,N.right=w,N.bottom=E,N.body=a,o(i,y,N))}}},m=function(e){var n,r,o,i,a=f,u=0,c=0,l=1,p=0,v=1;for(a[0]=g;l;){var h=a[p],m=h.body;l-=1,p+=1;var y=m!==e;m&&y?(r=m.pos.x-e.pos.x,o=m.pos.y-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),n=s*m.mass*e.mass/(i*i*i),u+=n*r,c+=n*o):y&&(r=h.massX/h.mass-e.pos.x,o=h.massY/h.mass-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),(h.right-h.left)/iu&&(t=u),u>o&&(o=u),r>s&&(r=s),s>i&&(i=s)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,p=0,g=v(),g.left=t,g.right=o,g.top=r,g.bottom=i,n=a-1,n>0&&(g.body=e[n]);n--;)h(e[n],g)};return{insertBodies:y,updateBodyForce:m,options:function(e){return e?("number"==typeof e.gravity&&(s=e.gravity),"number"==typeof e.theta&&(d=e.theta),this):{gravity:s,theta:d}}}}},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":25}],18:[function(e,n,t){function r(){this.stack=[],this.popIdx=0}function o(e,n){this.node=e,this.body=n}n.exports=r,r.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new o(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],19:[function(e,n,t){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],20:[function(e,n,t){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],21:[function(e,n,t){function r(e,n,t){var r;n=n||o,t=t||o,r="string"==typeof e?JSON.parse(e):e;var a,u=i();if(void 0===r.links||void 0===r.nodes)throw new Error("Cannot load graph without links and nodes");for(a=0;ae)throw new Error("Invalid number of nodes");var n,t=p();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function o(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=r(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function i(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=p();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function a(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=p();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function u(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=p();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function s(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=p();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function f(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=p();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var u=i*e*n,s=r+o*e+u;r>0&&a.addLink(s,r-1+o*e+u),o>0&&a.addLink(s,r+(o-1)*e+u),i>0&&a.addLink(s,r+o*e+(i-1)*e*n)}return a}function c(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=p(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function d(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=p();for(n=0;e>n;++n)t.addNode(n);return t}function l(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,u=e("ngraph.random").random(o||42),s=p();for(i=0;n>i;++i)s.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,s.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(u.nextDouble()n)return!1;B(),_.splice(n,1);var t=f(e.fromId),r=f(e.toId);return t&&(n=o(e,t.links),n>=0&&t.links.splice(n,1)),r&&(n=o(e,r.links),n>=0&&r.links.splice(n,1)),U(e,"remove"),F(),!0}function h(e,n){var t,r=f(e);if(!r)return null;for(t=0;tn;++n)e(_[n])}function x(e,n,t){var r=f(e);return r&&r.links&&"function"==typeof n?t?b(r.links,e,n):w(r.links,e,n):void 0}function w(e,n,t){for(var r,o=0;o0&&(O.fire("changed",M),M.length=0)}function N(){return Object.keys?k:A}function k(e){if("function"==typeof e)for(var n=Object.keys(j),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function i(e){this.id=e,this.links=[],this.data=null}function a(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=r;var u=e("ngraph.events")},{"ngraph.events":6}],24:[function(e,n,t){function r(e,n){var t;if(e||(e={}),n)for(t in n)if(n.hasOwnProperty(t)){var o=e.hasOwnProperty(t),i=typeof n[t],a=!o||typeof e[t]!==i;a?e[t]=n[t]:"object"===i&&(e[t]=r(e[t],n[t]))}return e}n.exports=r},{}],25:[function(e,n,t){function r(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function o(e,n){var t=n||r();if("function"!=typeof t.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var r,o,i;for(r=e.length-1;r>0;--r)o=t.next(r+1),i=e[o],e[o]=e[r],e[r]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,r,o;for(n=e.length-1;n>0;--n)r=t.next(n+1),o=e[r],e[r]=e[n],e[n]=o;return e}}}n.exports={random:r,randomIterator:o}},{}],26:[function(e,n,t){function r(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=r},{}],27:[function(e,n,t){function r(e,n){var t=o(e);if(void 0===n)return t;for(var r=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},A=function(e){p=!1,o.off("touchmove",k),o.off("touchend",A),o.off("touchcancel",A),c=null,r&&r(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,o.on("touchmove",k),o.on("touchend",A),o.on("touchcancel",A))},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b), -e.removeEventListener("touchstart",_),o.off("mousemove",w),o.off("mouseup",E),o.off("touchmove",k),o.off("touchend",A),o.off("touchcancel",A),P(null)}}}n.exports=r;var o=e("../Utils/documentEvents.js"),i=e("../Utils/browserInfo.js"),a=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":39,"../Utils/documentEvents.js":40,"../Utils/findElementPosition.js":41}],36:[function(e,n,t){function r(e,n){var t=o(n),r=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){r=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(r);var o=i[e.id];return o&&o.onStart&&o.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(r),r=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(r){var t=i[r.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=r;var o=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":57}],37:[function(e,n,t){function r(e,n){function t(e){return d[e]}n=o(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var r=i(n.seed),u=new a(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(e){return{x:r.next(n.maxX),y:r.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"==typeof z?z:!0}function r(){G=G||window.document.body,F=F||i(e,{springLength:80,springCoeff:2e-4}),O=O||a(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||s)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=f(function(){return p()},M)):(X=0,V=0,R=f(p,M)))}function g(){J||(W=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;en,t)})),e.forEachNode(E),T(),e.on("changed",j)}function D(){q=!1,T(),I(),u.off("resize",_),K.off(),R.stop(),e.forEachLink(function(e){n.renderLinks&&b(e)}),e.forEachNode(function(e){L(e),x(e)}),F.dispose(),N()}var M=30;n=n||{};var U,R,B,F=n.layout,O=n.graphics,G=n.container,z=void 0!==n.interactive?n.interactive:!0,q=!1,Y=!0,X=0,V=0,W=!1,H=!1,J=!1,$={offsetX:0,offsetY:0,scale:1},K=o({});return{run:function(e){return q||(r(),h(),P(),m(),S(),q=!0),v(e),this},reset:function(){O.resetScale(),m(),$.scale=1},pause:function(){J=!0,R.stop()},resume:function(){J=!1,R.restart()},rerender:function(){return l(),this},zoomOut:function(){return C(!0)},zoomIn:function(){return C(!1)},moveTo:function(e,n){O.graphCenterChanged($.offsetX-e*$.scale,$.offsetY-n*$.scale),l()},getGraphics:function(){return O},dispose:function(){D()},on:function(e,n){return K.on(e,n),this},off:function(e,n){return K.off(e,n),this}}}n.exports=r;var o=e("ngraph.events"),i=e("ngraph.forcelayout"),a=e("./svgGraphics.js"),u=e("../Utils/windowEvents.js"),s=e("../Input/domInputManager.js"),f=e("../Utils/timer.js"),c=e("../Utils/getDimensions.js"),d=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":34,"../Input/dragndrop.js":35,"../Utils/getDimensions.js":42,"../Utils/timer.js":46,"../Utils/windowEvents.js":47,"./svgGraphics.js":49,"ngraph.events":6,"ngraph.forcelayout":7}],49:[function(e,n,t){function r(){function e(){var e=o("svg");return n=o("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,r,u=0,s=0,f=1,c={},d={},l=function(e){return o("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(e){return o("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+u+","+s+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){u=e,s=n,w()},inputManager:a,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),a=n.getCTM().multiply(i);f=a.a,u=a.e,s=a.f;var c="matrix("+a.a+", 0, 0,"+a.d+","+a.e+","+a.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof r&&r(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):r=e),t},getSvgRoot:function(){return t}};return i(b),b}n.exports=r;var o=e("simplesvg"),i=e("ngraph.events"),a=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":34,"ngraph.events":6,simplesvg:27}],50:[function(e,n,t){function r(e){e=c(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,r,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=i(),P=a(),N=function(e){return u()},k=function(e){return s(3014898687)},A=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),r&&r.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(k=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:o,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,A()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],A()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,A(),I(this),y[0]},resetScale:function(){return j(),r&&(_(),A()),this},init:function(o){var i={};if(e.preserveDrawingBuffer&&(i.preserveDrawingBuffer=!0),n=o,_(),j(),n.appendChild(t),r=t.getContext("experimental-webgl",i),!r){var a="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(a),a}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var u=e.clearColorValue;r.clearColor(u.r,u.g,u.b,u.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}L.load(r),L.updateSize(d/2,l/2),P.load(r),P.updateSize(d/2,l/2),A(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!r&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!r&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x=e.x*(d/2),e.y=e.y*(-l/2),e},transformGraphToClientCoordinates:function(e){return e.x=e.x/(d/2),e.y=e.y/(-l/2),e.x=e.x*y[0]+y[12],e.y=e.y*y[5]+y[13],e.x=(e.x+1)*d/2,e.y=(1-e.y)*l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return f(T),T}n.exports=r;var o=e("../Input/webglInputManager.js"),i=e("../WebGL/webglLinkProgram.js"),a=e("../WebGL/webglNodeProgram.js"),u=e("../WebGL/webglSquare.js"),s=e("../WebGL/webglLine.js"),f=e("ngraph.events"),c=e("ngraph.merge")},{"../Input/webglInputManager.js":36,"../WebGL/webglLine.js":58,"../WebGL/webglLinkProgram.js":59,"../WebGL/webglNodeProgram.js":60,"../WebGL/webglSquare.js":61,"ngraph.events":6,"ngraph.merge":24}],51:[function(e,n,t){function r(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=r},{}],52:[function(e,n,t){function r(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=r},{}],53:[function(e,n,t){function r(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function r(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function i(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=r},{}],54:[function(e,n,t){function r(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!o(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:r,getCoordinates:a,load:u};return E}function o(e){return 0===(e&e-1)}var i=e("./texture.js");n.exports=r},{"./texture.js":52}],55:[function(e,n,t){function r(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=r},{}],56:[function(e,n,t){function r(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=o(),k=i(),A=1024,j=0,_=new Float32Array(64);return{load:t,position:r,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function o(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function i(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var a=e("./webglAtlas.js"),u=e("./webgl.js");n.exports=r},{"./webgl.js":53,"./webglAtlas.js":54}],57:[function(e,n,t){function r(e){function n(){x=null}function t(e){x=e}function r(e){return"function"==typeof e&&k.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&r[0]===t?g(k,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],k=[],A=e.getGraphicsRoot();h(A);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:r,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var o=e("../Utils/documentEvents.js");n.exports=r},{"../Utils/documentEvents.js":40}],58:[function(e,n,t){function r(e){return{color:o(e)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],59:[function(e,n,t){function r(){var e,n,t,r,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,r=o(a),e=r.createProgram(v,p),n.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&r.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&r.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],60:[function(e,n,t){function r(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=o(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=-n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function r(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(N,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:r,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],61:[function(e,n,t){function r(e,n){return{size:"number"==typeof e?e:10,color:o(n)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],62:[function(e,n,t){n.exports="0.8.1"},{}]},{},[1])(1)}); \ No newline at end of file +e.removeEventListener("touchstart",_),o.off("mousemove",w),o.off("mouseup",E),o.off("touchmove",k),o.off("touchend",A),o.off("touchcancel",A),P(null)}}}n.exports=r;var o=e("../Utils/documentEvents.js"),i=e("../Utils/browserInfo.js"),a=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":39,"../Utils/documentEvents.js":40,"../Utils/findElementPosition.js":41}],36:[function(e,n,t){function r(e,n){var t=o(n),r=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){r=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(r);var o=i[e.id];return o&&o.onStart&&o.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(r),r=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(r){var t=i[r.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=r;var o=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":57}],37:[function(e,n,t){function r(e,n){function t(e){return d[e]}n=o(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var r=i(n.seed),u=new a(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(e){return{x:r.next(n.maxX),y:r.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"==typeof z?z:!0}function r(){G=G||window.document.body,F=F||i(e,{springLength:80,springCoeff:2e-4}),O=O||a(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||s)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=f(function(){return p()},M)):(X=0,V=0,R=f(p,M)))}function g(){J||(W=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;en,t)})),e.forEachNode(E),T(),e.on("changed",j)}function D(){q=!1,T(),I(),u.off("resize",_),K.off(),R.stop(),e.forEachLink(function(e){n.renderLinks&&b(e)}),e.forEachNode(function(e){L(e),x(e)}),F.dispose(),N()}var M=30;n=n||{};var U,R,B,F=n.layout,O=n.graphics,G=n.container,z=void 0!==n.interactive?n.interactive:!0,q=!1,Y=!0,X=0,V=0,W=!1,H=!1,J=!1,$={offsetX:0,offsetY:0,scale:1},K=o({});return{run:function(e){return q||(r(),h(),P(),m(),S(),q=!0),v(e),this},reset:function(){O.resetScale(),m(),$.scale=1},pause:function(){J=!0,R.stop()},resume:function(){J=!1,R.restart()},rerender:function(){return l(),this},zoomOut:function(){return C(!0)},zoomIn:function(){return C(!1)},moveTo:function(e,n){O.graphCenterChanged($.offsetX-e*$.scale,$.offsetY-n*$.scale),l()},getGraphics:function(){return O},dispose:function(){D()},on:function(e,n){return K.on(e,n),this},off:function(e,n){return K.off(e,n),this}}}n.exports=r;var o=e("ngraph.events"),i=e("ngraph.forcelayout"),a=e("./svgGraphics.js"),u=e("../Utils/windowEvents.js"),s=e("../Input/domInputManager.js"),f=e("../Utils/timer.js"),c=e("../Utils/getDimensions.js"),d=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":34,"../Input/dragndrop.js":35,"../Utils/getDimensions.js":42,"../Utils/timer.js":46,"../Utils/windowEvents.js":47,"./svgGraphics.js":49,"ngraph.events":6,"ngraph.forcelayout":7}],49:[function(e,n,t){function r(){function e(){var e=o("svg");return n=o("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,r,u=0,s=0,f=1,c={},d={},l=function(e){return o("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(e){return o("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+u+","+s+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){u=e,s=n,w()},inputManager:a,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),a=n.getCTM().multiply(i);f=a.a,u=a.e,s=a.f;var c="matrix("+a.a+", 0, 0,"+a.d+","+a.e+","+a.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof r&&r(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):r=e),t},getSvgRoot:function(){return t}};return i(b),b}n.exports=r;var o=e("simplesvg"),i=e("ngraph.events"),a=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":34,"ngraph.events":6,simplesvg:27}],50:[function(e,n,t){function r(e){e=c(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,r,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=i(),P=a(),N=function(e){return u()},k=function(e){return s(3014898687)},A=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),r&&r.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(k=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:o,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,A()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],A()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,A(),I(this),y[0]},resetScale:function(){return j(),r&&(_(),A()),this},init:function(o){var i={};if(e.preserveDrawingBuffer&&(i.preserveDrawingBuffer=!0),n=o,_(),j(),n.appendChild(t),r=t.getContext("experimental-webgl",i),!r){var a="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(a),a}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var u=e.clearColorValue;r.clearColor(u.r,u.g,u.b,u.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}L.load(r),L.updateSize(d/2,l/2),P.load(r),P.updateSize(d/2,l/2),A(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!r&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!r&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x=e.x*(d/2),e.y=e.y*(-l/2),e},transformGraphToClientCoordinates:function(e){return e.x=e.x/(d/2),e.y=e.y/(-l/2),e.x=e.x*y[0]+y[12],e.y=e.y*y[5]+y[13],e.x=(e.x+1)*d/2,e.y=(1-e.y)*l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return f(T),T}n.exports=r;var o=e("../Input/webglInputManager.js"),i=e("../WebGL/webglLinkProgram.js"),a=e("../WebGL/webglNodeProgram.js"),u=e("../WebGL/webglSquare.js"),s=e("../WebGL/webglLine.js"),f=e("ngraph.events"),c=e("ngraph.merge")},{"../Input/webglInputManager.js":36,"../WebGL/webglLine.js":58,"../WebGL/webglLinkProgram.js":59,"../WebGL/webglNodeProgram.js":60,"../WebGL/webglSquare.js":61,"ngraph.events":6,"ngraph.merge":24}],51:[function(e,n,t){function r(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=r},{}],52:[function(e,n,t){function r(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=r},{}],53:[function(e,n,t){function r(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function r(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function i(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=r},{}],54:[function(e,n,t){function r(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!o(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:r,getCoordinates:a,load:u};return E}function o(e){return 0===(e&e-1)}var i=e("./texture.js");n.exports=r},{"./texture.js":52}],55:[function(e,n,t){function r(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=r},{}],56:[function(e,n,t){function r(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=o(),k=i(),A=1024,j=0,_=new Float32Array(64);return{load:t,position:r,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function o(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function i(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var a=e("./webglAtlas.js"),u=e("./webgl.js");n.exports=r},{"./webgl.js":53,"./webglAtlas.js":54}],57:[function(e,n,t){function r(e){function n(){x=null}function t(e){x=e}function r(e){return"function"==typeof e&&k.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&u?g(k,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],k=[],A=e.getGraphicsRoot();h(A);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:r,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var o=e("../Utils/documentEvents.js");n.exports=r},{"../Utils/documentEvents.js":40}],58:[function(e,n,t){function r(e){return{color:o(e)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],59:[function(e,n,t){function r(){var e,n,t,r,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,r=o(a),e=r.createProgram(v,p),n.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&r.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&r.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],60:[function(e,n,t){function r(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=o(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=-n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function r(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(N,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:r,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],61:[function(e,n,t){function r(e,n){return{size:"number"==typeof e?e:10,color:o(n)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],62:[function(e,n,t){n.exports="0.8.1"},{}]},{},[1])(1)}); \ No newline at end of file From 12ccef6ddd50743af96c5ab8da9e12eb8d2b5db8 Mon Sep 17 00:00:00 2001 From: anvaka Date: Fri, 9 Sep 2016 20:27:22 -0700 Subject: [PATCH 225/276] 0.8.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ce90d0e..4cfe071 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.8.1", + "version": "0.8.2", "description": "Graph Drawing Library", "main": "src/viva", "directories": { From eb3f39f16c5fdd94271619dc33b9fd76097de977 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 25 Sep 2016 20:00:13 -0700 Subject: [PATCH 226/276] Typo --- demos/other/webglCustomNode.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demos/other/webglCustomNode.html b/demos/other/webglCustomNode.html index 77760c4..4ea6ca9 100644 --- a/demos/other/webglCustomNode.html +++ b/demos/other/webglCustomNode.html @@ -71,7 +71,7 @@ '}'].join('\n'), nodesVS = [ 'attribute vec2 a_vertexPos;', - // Pack clor and size into vector. First elemnt is color, second - size. + // Pack color and size into vector. First elemnt is color, second - size. // Since it's floating point we can only use 24 bit to pack colors... // thus alpha channel is dropped, and is always assumed to be 1. 'attribute vec2 a_customAttributes;', From e0464e1304283a34d94e73fcd169ee4df827bb7c Mon Sep 17 00:00:00 2001 From: Andrei Kashcha Date: Fri, 21 Apr 2017 15:03:04 -0700 Subject: [PATCH 227/276] Update README.md Removing note update performance. It was written long time ago, and I need to re-run performance measurements again. Until then, removing the note to not mislead people --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7f031f5..5c97cf9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ VivaGraph [![Build Status](https://travis-ci.org/anvaka/VivaGraphJS.svg)](https://travis-ci.org/anvaka/VivaGraphJS) ================================================== -**VivaGraphJS** is the fastest graph drawing javascript library ([proof](https://www.youtube.com/watch?v=Ax7KSQZ0_hk)). It is designed to be extensible and to support different +**VivaGraphJS** is designed to be extensible and to support different rendering engines and layout algorithms. Underlying modules can be found via [ngraph](https://www.npmjs.com/search?q=ngraph) query. [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/anvaka/VivaGraphJS?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) From dc8a2b05fdfaed5df0120630763a5e3cf4b4b092 Mon Sep 17 00:00:00 2001 From: Tomasz Cichocinski Date: Sun, 23 Apr 2017 23:31:59 +0200 Subject: [PATCH 228/276] Fire public event on renderer drag action --- src/View/renderer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/View/renderer.js b/src/View/renderer.js index 558cb85..9d723f2 100644 --- a/src/View/renderer.js +++ b/src/View/renderer.js @@ -435,6 +435,7 @@ function renderer(graph, settings) { graphics.translateRel(offset.x, offset.y); renderGraph(); + publicEvents.fire('drag', offset); }); } From b9c8ddde88e8b0fdb68cb5f8e0be16850c37cf63 Mon Sep 17 00:00:00 2001 From: Andriy Kashcha Date: Mon, 24 Apr 2017 21:45:09 -0700 Subject: [PATCH 229/276] applying patch --- dist/vivagraph.js | 3325 +++++++++++++++++++++-------------------- dist/vivagraph.min.js | 4 +- 2 files changed, 1665 insertions(+), 1664 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index de13506..29c4caa 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -112,7 +112,55 @@ Viva.Graph = { module.exports = Viva; -},{"./Algorithms/centrality.js":32,"./Algorithms/operations.js":33,"./Input/domInputManager.js":34,"./Input/dragndrop.js":35,"./Input/webglInputManager.js":36,"./Layout/constant.js":37,"./Utils/backwardCompatibleEvents.js":38,"./Utils/browserInfo.js":39,"./Utils/findElementPosition.js":41,"./Utils/getDimensions.js":42,"./Utils/intersectRect.js":43,"./Utils/rect.js":45,"./Utils/timer.js":46,"./View/renderer.js":48,"./View/svgGraphics.js":49,"./View/webglGraphics.js":50,"./WebGL/parseColor.js":51,"./WebGL/texture.js":52,"./WebGL/webgl.js":53,"./WebGL/webglAtlas.js":54,"./WebGL/webglImage.js":55,"./WebGL/webglImageNodeProgram.js":56,"./WebGL/webglInputEvents.js":57,"./WebGL/webglLine.js":58,"./WebGL/webglLinkProgram.js":59,"./WebGL/webglNodeProgram.js":60,"./WebGL/webglSquare.js":61,"./version.js":62,"gintersect":2,"ngraph.events":6,"ngraph.forcelayout":7,"ngraph.fromjson":21,"ngraph.generators":22,"ngraph.graph":23,"ngraph.merge":24,"ngraph.random":25,"ngraph.tojson":26,"simplesvg":27}],2:[function(require,module,exports){ +},{"./Algorithms/centrality.js":32,"./Algorithms/operations.js":33,"./Input/domInputManager.js":34,"./Input/dragndrop.js":35,"./Input/webglInputManager.js":36,"./Layout/constant.js":37,"./Utils/backwardCompatibleEvents.js":38,"./Utils/browserInfo.js":39,"./Utils/findElementPosition.js":41,"./Utils/getDimensions.js":42,"./Utils/intersectRect.js":43,"./Utils/rect.js":45,"./Utils/timer.js":46,"./View/renderer.js":48,"./View/svgGraphics.js":49,"./View/webglGraphics.js":50,"./WebGL/parseColor.js":51,"./WebGL/texture.js":52,"./WebGL/webgl.js":53,"./WebGL/webglAtlas.js":54,"./WebGL/webglImage.js":55,"./WebGL/webglImageNodeProgram.js":56,"./WebGL/webglInputEvents.js":57,"./WebGL/webglLine.js":58,"./WebGL/webglLinkProgram.js":59,"./WebGL/webglNodeProgram.js":60,"./WebGL/webglSquare.js":61,"./version.js":62,"gintersect":3,"ngraph.events":7,"ngraph.forcelayout":9,"ngraph.fromjson":10,"ngraph.generators":11,"ngraph.graph":12,"ngraph.merge":13,"ngraph.random":26,"ngraph.tojson":27,"simplesvg":28}],2:[function(require,module,exports){ +addEventListener.removeEventListener = removeEventListener +addEventListener.addEventListener = addEventListener + +module.exports = addEventListener + +var Events = null + +function addEventListener(el, eventName, listener, useCapture) { + Events = Events || ( + document.addEventListener ? + {add: stdAttach, rm: stdDetach} : + {add: oldIEAttach, rm: oldIEDetach} + ) + + return Events.add(el, eventName, listener, useCapture) +} + +function removeEventListener(el, eventName, listener, useCapture) { + Events = Events || ( + document.addEventListener ? + {add: stdAttach, rm: stdDetach} : + {add: oldIEAttach, rm: oldIEDetach} + ) + + return Events.rm(el, eventName, listener, useCapture) +} + +function stdAttach(el, eventName, listener, useCapture) { + el.addEventListener(eventName, listener, useCapture) +} + +function stdDetach(el, eventName, listener, useCapture) { + el.removeEventListener(eventName, listener, useCapture) +} + +function oldIEAttach(el, eventName, listener, useCapture) { + if(useCapture) { + throw new Error('cannot useCapture in oldIE') + } + + el.attachEvent('on' + eventName, listener) +} + +function oldIEDetach(el, eventName, listener, useCapture) { + el.detachEvent('on' + eventName, listener) +} + +},{}],3:[function(require,module,exports){ module.exports = intersect; /** @@ -213,11 +261,11 @@ function intersect( return result; } -},{}],3:[function(require,module,exports){ +},{}],4:[function(require,module,exports){ module.exports.degree = require('./src/degree.js'); module.exports.betweenness = require('./src/betweenness.js'); -},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(require,module,exports){ +},{"./src/betweenness.js":5,"./src/degree.js":6}],5:[function(require,module,exports){ module.exports = betweennes; /** @@ -329,7 +377,7 @@ function betweennes(graph, oriented) { } } -},{}],5:[function(require,module,exports){ +},{}],6:[function(require,module,exports){ module.exports = degree; /** @@ -390,7 +438,7 @@ function inoutDegreeCalculator(links) { return links.length; } -},{}],6:[function(require,module,exports){ +},{}],7:[function(require,module,exports){ module.exports = function(subject) { validateSubject(subject); @@ -480,7 +528,53 @@ function validateSubject(subject) { } } -},{}],7:[function(require,module,exports){ +},{}],8:[function(require,module,exports){ +module.exports = exposeProperties; + +/** + * Augments `target` object with getter/setter functions, which modify settings + * + * @example + * var target = {}; + * exposeProperties({ age: 42}, target); + * target.age(); // returns 42 + * target.age(24); // make age 24; + * + * var filteredTarget = {}; + * exposeProperties({ age: 42, name: 'John'}, filteredTarget, ['name']); + * filteredTarget.name(); // returns 'John' + * filteredTarget.age === undefined; // true + */ +function exposeProperties(settings, target, filter) { + var needsFilter = Object.prototype.toString.call(filter) === '[object Array]'; + if (needsFilter) { + for (var i = 0; i < filter.length; ++i) { + augment(settings, target, filter[i]); + } + } else { + for (var key in settings) { + augment(settings, target, key); + } + } +} + +function augment(source, target, key) { + if (source.hasOwnProperty(key)) { + if (typeof target[key] === 'function') { + // this accessor is already defined. Ignore it + return; + } + target[key] = function (value) { + if (value !== undefined) { + source[key] = value; + return target; + } + return source[key]; + } + } +} + +},{}],9:[function(require,module,exports){ module.exports = createLayout; module.exports.simulator = require('ngraph.physics.simulator'); @@ -784,1952 +878,1906 @@ function createLayout(graph, physicsSettings) { function noop() { } -},{"ngraph.physics.simulator":8}],8:[function(require,module,exports){ -/** - * Manages a simulation of physical forces acting on bodies and springs. - */ -module.exports = physicsSimulator; +},{"ngraph.physics.simulator":15}],10:[function(require,module,exports){ +module.exports = load; -function physicsSimulator(settings) { - var Spring = require('./lib/spring'); - var expose = require('ngraph.expose'); - var merge = require('ngraph.merge'); +var createGraph = require('ngraph.graph'); - settings = merge(settings, { - /** - * Ideal length for links (springs in physical model). - */ - springLength: 30, +function load(jsonGraph, nodeTransform, linkTransform) { + var stored; + nodeTransform = nodeTransform || id; + linkTransform = linkTransform || id; + if (typeof jsonGraph === 'string') { + stored = JSON.parse(jsonGraph); + } else { + stored = jsonGraph; + } - /** - * Hook's law coefficient. 1 - solid spring. - */ - springCoeff: 0.0008, + var graph = createGraph(), + i; - /** - * Coulomb's law coefficient. It's used to repel nodes thus should be negative - * if you make it positive nodes start attract each other :). - */ - gravity: -1.2, + if (stored.links === undefined || stored.nodes === undefined) { + throw new Error('Cannot load graph without links and nodes'); + } - /** - * Theta coefficient from Barnes Hut simulation. Ranged between (0, 1). - * The closer it's to 1 the more nodes algorithm will have to go through. - * Setting it to one makes Barnes Hut simulation no different from - * brute-force forces calculation (each node is considered). - */ - theta: 0.8, + for (i = 0; i < stored.nodes.length; ++i) { + var parsedNode = nodeTransform(stored.nodes[i]); + if (!parsedNode.hasOwnProperty('id')) { + throw new Error('Graph node format is invalid: Node id is missing'); + } - /** - * Drag force coefficient. Used to slow down system, thus should be less than 1. - * The closer it is to 0 the less tight system will be. - */ - dragCoeff: 0.02, + graph.addNode(parsedNode.id, parsedNode.data); + } - /** - * Default time step (dt) for forces integration - */ - timeStep : 20, + for (i = 0; i < stored.links.length; ++i) { + var link = linkTransform(stored.links[i]); + if (!link.hasOwnProperty('fromId') || !link.hasOwnProperty('toId')) { + throw new Error('Graph link format is invalid. Both fromId and toId are required'); + } - /** - * Maximum movement of the system which can be considered as stabilized - */ - stableThreshold: 0.009 - }); + graph.addLink(link.fromId, link.toId, link.data); + } - // We allow clients to override basic factory methods: - var createQuadTree = settings.createQuadTree || require('ngraph.quadtreebh'); - var createBounds = settings.createBounds || require('./lib/bounds'); - var createDragForce = settings.createDragForce || require('./lib/dragForce'); - var createSpringForce = settings.createSpringForce || require('./lib/springForce'); - var integrate = settings.integrator || require('./lib/eulerIntegrator'); - var createBody = settings.createBody || require('./lib/createBody'); + return graph; +} - var bodies = [], // Bodies in this simulation. - springs = [], // Springs in this simulation. - quadTree = createQuadTree(settings), - bounds = createBounds(bodies, settings), - springForce = createSpringForce(settings), - dragForce = createDragForce(settings); +function id(x) { return x; } - var publicApi = { - /** - * Array of bodies, registered with current simulator - * - * Note: To add new body, use addBody() method. This property is only - * exposed for testing/performance purposes. - */ - bodies: bodies, +},{"ngraph.graph":12}],11:[function(require,module,exports){ +module.exports = { + ladder: ladder, + complete: complete, + completeBipartite: completeBipartite, + balancedBinTree: balancedBinTree, + path: path, + circularLadder: circularLadder, + grid: grid, + grid3: grid3, + noLinks: noLinks, + wattsStrogatz: wattsStrogatz +}; - /** - * Array of springs, registered with current simulator - * - * Note: To add new spring, use addSpring() method. This property is only - * exposed for testing/performance purposes. - */ - springs: springs, +var createGraph = require('ngraph.graph'); - /** - * Returns settings with which current simulator was initialized - */ - settings: settings, +function ladder(n) { +/** + * Ladder graph is a graph in form of ladder + * @param {Number} n Represents number of steps in the ladder + */ + if (!n || n < 0) { + throw new Error("Invalid number of nodes"); + } - /** - * Performs one step of force simulation. - * - * @returns {boolean} true if system is considered stable; False otherwise. - */ - step: function () { - accumulateForces(); - var totalMovement = integrate(bodies, settings.timeStep); + var g = createGraph(), + i; - bounds.update(); + for (i = 0; i < n - 1; ++i) { + g.addLink(i, i + 1); + // first row + g.addLink(n + i, n + i + 1); + // second row + g.addLink(i, n + i); + // ladder's step + } - return totalMovement < settings.stableThreshold; - }, + g.addLink(n - 1, 2 * n - 1); + // last step in the ladder; - /** - * Adds body to the system - * - * @param {ngraph.physics.primitives.Body} body physical body - * - * @returns {ngraph.physics.primitives.Body} added body - */ - addBody: function (body) { - if (!body) { - throw new Error('Body is required'); - } - bodies.push(body); - - return body; - }, - - /** - * Adds body to the system at given position - * - * @param {Object} pos position of a body - * - * @returns {ngraph.physics.primitives.Body} added body - */ - addBodyAt: function (pos) { - if (!pos) { - throw new Error('Body position is required'); - } - var body = createBody(pos); - bodies.push(body); + return g; +} - return body; - }, +function circularLadder(n) { +/** + * Circular ladder with n steps. + * + * @param {Number} n of steps in the ladder. + */ + if (!n || n < 0) { + throw new Error("Invalid number of nodes"); + } - /** - * Removes body from the system - * - * @param {ngraph.physics.primitives.Body} body to remove - * - * @returns {Boolean} true if body found and removed. falsy otherwise; - */ - removeBody: function (body) { - if (!body) { return; } + var g = ladder(n); - var idx = bodies.indexOf(body); - if (idx < 0) { return; } + g.addLink(0, n - 1); + g.addLink(n, 2 * n - 1); + return g; +} - bodies.splice(idx, 1); - if (bodies.length === 0) { - bounds.reset(); - } - return true; - }, +function complete(n) { +/** + * Complete graph Kn. + * + * @param {Number} n represents number of nodes in the complete graph. + */ + if (!n || n < 1) { + throw new Error("At least two nodes are expected for complete graph"); + } - /** - * Adds a spring to this simulation. - * - * @returns {Object} - a handle for a spring. If you want to later remove - * spring pass it to removeSpring() method. - */ - addSpring: function (body1, body2, springLength, springWeight, springCoefficient) { - if (!body1 || !body2) { - throw new Error('Cannot add null spring to force simulator'); - } + var g = createGraph(), + i, + j; - if (typeof springLength !== 'number') { - springLength = -1; // assume global configuration + for (i = 0; i < n; ++i) { + for (j = i + 1; j < n; ++j) { + if (i !== j) { + g.addLink(i, j); } + } + } - var spring = new Spring(body1, body2, springLength, springCoefficient >= 0 ? springCoefficient : -1, springWeight); - springs.push(spring); + return g; +} - // TODO: could mark simulator as dirty. - return spring; - }, +function completeBipartite (n, m) { +/** + * Complete bipartite graph K n,m. Each node in the + * first partition is connected to all nodes in the second partition. + * + * @param {Number} n represents number of nodes in the first graph partition + * @param {Number} m represents number of nodes in the second graph partition + */ + if (!n || !m || n < 0 || m < 0) { + throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0"); + } - /** - * Removes spring from the system - * - * @param {Object} spring to remove. Spring is an object returned by addSpring - * - * @returns {Boolean} true if spring found and removed. falsy otherwise; - */ - removeSpring: function (spring) { - if (!spring) { return; } - var idx = springs.indexOf(spring); - if (idx > -1) { - springs.splice(idx, 1); - return true; - } - }, + var g = createGraph(), + i, j; - getBestNewBodyPosition: function (neighbors) { - return bounds.getBestNewPosition(neighbors); - }, + for (i = 0; i < n; ++i) { + for (j = n; j < n + m; ++j) { + g.addLink(i, j); + } + } - /** - * Returns bounding box which covers all bodies - */ - getBBox: function () { - return bounds.box; - }, + return g; +} - gravity: function (value) { - if (value !== undefined) { - settings.gravity = value; - quadTree.options({gravity: value}); - return this; - } else { - return settings.gravity; - } - }, +function path(n) { +/** + * Path graph with n steps. + * + * @param {Number} n number of nodes in the path + */ + if (!n || n < 0) { + throw new Error("Invalid number of nodes"); + } - theta: function (value) { - if (value !== undefined) { - settings.theta = value; - quadTree.options({theta: value}); - return this; - } else { - return settings.theta; - } - } - }; + var g = createGraph(), + i; - // allow settings modification via public API: - expose(settings, publicApi); + g.addNode(0); - return publicApi; + for (i = 1; i < n; ++i) { + g.addLink(i - 1, i); + } - function accumulateForces() { - // Accumulate forces acting on bodies. - var body, - i = bodies.length; + return g; +} - if (i) { - // only add bodies if there the array is not empty: - quadTree.insertBodies(bodies); // performance: O(n * log n) - while (i--) { - body = bodies[i]; - // If body is pinned there is no point updating its forces - it should - // never move: - if (!body.isPinned) { - body.force.reset(); - quadTree.updateBodyForce(body); - dragForce.update(body); - } - } - } +function grid(n, m) { +/** + * Grid graph with n rows and m columns. + * + * @param {Number} n of rows in the graph. + * @param {Number} m of columns in the graph. + */ + if (n < 1 || m < 1) { + throw new Error("Invalid number of nodes in grid graph"); + } + var g = createGraph(), + i, + j; + if (n === 1 && m === 1) { + g.addNode(0); + return g; + } - i = springs.length; - while(i--) { - springForce.update(springs[i]); + for (i = 0; i < n; ++i) { + for (j = 0; j < m; ++j) { + var node = i + j * n; + if (i > 0) { g.addLink(node, i - 1 + j * n); } + if (j > 0) { g.addLink(node, i + (j - 1) * n); } } } -}; - -},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":24,"ngraph.quadtreebh":17}],9:[function(require,module,exports){ -module.exports = function (bodies, settings) { - var random = require('ngraph.random').random(42); - var boundingBox = { x1: 0, y1: 0, x2: 0, y2: 0 }; - - return { - box: boundingBox, - update: updateBoundingBox, + return g; +} - reset : function () { - boundingBox.x1 = boundingBox.y1 = 0; - boundingBox.x2 = boundingBox.y2 = 0; - }, +function grid3(n, m, z) { +/** + * 3D grid with n rows and m columns and z levels. + * + * @param {Number} n of rows in the graph. + * @param {Number} m of columns in the graph. + * @param {Number} z of levels in the graph. + */ + if (n < 1 || m < 1 || z < 1) { + throw new Error("Invalid number of nodes in grid3 graph"); + } + var g = createGraph(), + i, j, k; - getBestNewPosition: function (neighbors) { - var graphRect = boundingBox; + if (n === 1 && m === 1 && z === 1) { + g.addNode(0); + return g; + } - var baseX = 0, baseY = 0; - - if (neighbors.length) { - for (var i = 0; i < neighbors.length; ++i) { - baseX += neighbors[i].pos.x; - baseY += neighbors[i].pos.y; - } - - baseX /= neighbors.length; - baseY /= neighbors.length; - } else { - baseX = (graphRect.x1 + graphRect.x2) / 2; - baseY = (graphRect.y1 + graphRect.y2) / 2; + for (k = 0; k < z; ++k) { + for (i = 0; i < n; ++i) { + for (j = 0; j < m; ++j) { + var level = k * n * m; + var node = i + j * n + level; + if (i > 0) { g.addLink(node, i - 1 + j * n + level); } + if (j > 0) { g.addLink(node, i + (j - 1) * n + level); } + if (k > 0) { g.addLink(node, i + j * n + (k - 1) * n * m ); } } - - var springLength = settings.springLength; - return { - x: baseX + random.next(springLength) - springLength / 2, - y: baseY + random.next(springLength) - springLength / 2 - }; } - }; - - function updateBoundingBox() { - var i = bodies.length; - if (i === 0) { return; } // don't have to wory here. + } - var x1 = Number.MAX_VALUE, - y1 = Number.MAX_VALUE, - x2 = Number.MIN_VALUE, - y2 = Number.MIN_VALUE; + return g; +} - while(i--) { - // this is O(n), could it be done faster with quadtree? - // how about pinned nodes? - var body = bodies[i]; - if (body.isPinned) { - body.pos.x = body.prevPos.x; - body.pos.y = body.prevPos.y; - } else { - body.prevPos.x = body.pos.x; - body.prevPos.y = body.pos.y; - } - if (body.pos.x < x1) { - x1 = body.pos.x; - } - if (body.pos.x > x2) { - x2 = body.pos.x; - } - if (body.pos.y < y1) { - y1 = body.pos.y; - } - if (body.pos.y > y2) { - y2 = body.pos.y; - } - } +function balancedBinTree(n) { +/** + * Balanced binary tree with n levels. + * + * @param {Number} n of levels in the binary tree + */ + if (n < 0) { + throw new Error("Invalid number of nodes in balanced tree"); + } + var g = createGraph(), + count = Math.pow(2, n), + level; - boundingBox.x1 = x1; - boundingBox.x2 = x2; - boundingBox.y1 = y1; - boundingBox.y2 = y2; + if (n === 0) { + g.addNode(1); } -} -},{"ngraph.random":25}],10:[function(require,module,exports){ -var physics = require('ngraph.physics.primitives'); + for (level = 1; level < count; ++level) { + var root = level, + left = root * 2, + right = root * 2 + 1; -module.exports = function(pos) { - return new physics.Body(pos); + g.addLink(root, left); + g.addLink(root, right); + } + + return g; } -},{"ngraph.physics.primitives":16}],11:[function(require,module,exports){ +function noLinks(n) { /** - * Represents drag force, which reduces force value on each step by given - * coefficient. + * Graph with no links * - * @param {Object} options for the drag force - * @param {Number=} options.dragCoeff drag force coefficient. 0.1 by default + * @param {Number} n of nodes in the graph */ -module.exports = function (options) { - var merge = require('ngraph.merge'), - expose = require('ngraph.expose'); - - options = merge(options, { - dragCoeff: 0.02 - }); - - var api = { - update : function (body) { - body.force.x -= options.dragCoeff * body.velocity.x; - body.force.y -= options.dragCoeff * body.velocity.y; - } - }; + if (n < 0) { + throw new Error("Number of nodes shoul be >= 0"); + } - // let easy access to dragCoeff: - expose(options, api, ['dragCoeff']); + var g = createGraph(), i; + for (i = 0; i < n; ++i) { + g.addNode(i); + } - return api; -}; + return g; +} -},{"ngraph.expose":15,"ngraph.merge":24}],12:[function(require,module,exports){ +function wattsStrogatz(n, k, p, seed) { /** - * Performs forces integration, using given timestep. Uses Euler method to solve - * differential equation (http://en.wikipedia.org/wiki/Euler_method ). + * Watts-Strogatz small-world graph. * - * @returns {Number} squared distance of total position updates. - */ + * @param {Number} n The number of nodes + * @param {Number} k Each node is connected to k nearest neighbors in ring topology + * @param {Number} p The probability of rewiring each edge -module.exports = integrate; + * @see https://github.com/networkx/networkx/blob/master/networkx/generators/random_graphs.py + */ + if (k >= n) throw new Error('Choose smaller `k`. It cannot be larger than number of nodes `n`'); -function integrate(bodies, timeStep) { - var dx = 0, tx = 0, - dy = 0, ty = 0, - i, - max = bodies.length; - for (i = 0; i < max; ++i) { - var body = bodies[i], - coeff = timeStep / body.mass; + var random = require('ngraph.random').random(seed || 42); - body.velocity.x += coeff * body.force.x; - body.velocity.y += coeff * body.force.y; - var vx = body.velocity.x, - vy = body.velocity.y, - v = Math.sqrt(vx * vx + vy * vy); + var g = createGraph(), i, to; + for (i = 0; i < n; ++i) { + g.addNode(i); + } - if (v > 1) { - body.velocity.x = vx / v; - body.velocity.y = vy / v; + // connect each node to k/2 neighbors + var neighborsSize = Math.floor(k/2 + 1); + for (var j = 1; j < neighborsSize; ++j) { + for (i = 0; i < n; ++i) { + to = (j + i) % n; + g.addLink(i, to); } + } - dx = timeStep * body.velocity.x; - dy = timeStep * body.velocity.y; - - body.pos.x += dx; - body.pos.y += dy; + // rewire edges from each node + // loop over all nodes in order (label) and neighbors in order (distance) + // no self loops or multiple edges allowed + for (j = 1; j < neighborsSize; ++j) { + for (i = 0; i < n; ++i) { + if (random.nextDouble() < p) { + var from = i; + to = (j + i) % n; - tx += Math.abs(dx); ty += Math.abs(dy); + var newTo = random.next(n); + var needsRewire = (newTo === from || g.hasLink(from, newTo)); + if (needsRewire && g.getLinks(from).length === n - 1) { + // we cannot rewire this node, it has too many links. + continue; + } + // Enforce no self-loops or multiple edges + while (needsRewire) { + newTo = random.next(n); + needsRewire = (newTo === from || g.hasLink(from, newTo)); + } + var link = g.hasLink(from, to); + g.removeLink(link); + g.addLink(from, newTo); + } + } } - return (tx * tx + ty * ty)/bodies.length; + return g; } -},{}],13:[function(require,module,exports){ -module.exports = Spring; +},{"ngraph.graph":12,"ngraph.random":26}],12:[function(require,module,exports){ +/** + * @fileOverview Contains definition of the core graph object. + */ /** - * Represents a physical spring. Spring connects two bodies, has rest length - * stiffness coefficient and optional weight + * @example + * var graph = require('ngraph.graph')(); + * graph.addNode(1); // graph has one node. + * graph.addLink(2, 3); // now graph contains three nodes and one link. + * */ -function Spring(fromBody, toBody, length, coeff, weight) { - this.from = fromBody; - this.to = toBody; - this.length = length; - this.coeff = coeff; +module.exports = createGraph; - this.weight = typeof weight === 'number' ? weight : 1; -}; +var eventify = require('ngraph.events'); -},{}],14:[function(require,module,exports){ /** - * Represents spring force, which updates forces acting on two bodies, conntected - * by a spring. - * - * @param {Object} options for the spring force - * @param {Number=} options.springCoeff spring force coefficient. - * @param {Number=} options.springLength desired length of a spring at rest. + * Creates a new graph */ -module.exports = function (options) { - var merge = require('ngraph.merge'); - var random = require('ngraph.random').random(42); - var expose = require('ngraph.expose'); +function createGraph(options) { + // Graph structure is maintained as dictionary of nodes + // and array of links. Each node has 'links' property which + // hold all links related to that node. And general links + // array is used to speed up all links enumeration. This is inefficient + // in terms of memory, but simplifies coding. + options = options || {}; + if (options.uniqueLinkId === undefined) { + // Request each link id to be unique between same nodes. This negatively + // impacts `addLink()` performance (O(n), where n - number of edges of each + // vertex), but makes operations with multigraphs more accessible. + options.uniqueLinkId = true; + } - options = merge(options, { - springCoeff: 0.0002, - springLength: 80 - }); + var nodes = typeof Object.create === 'function' ? Object.create(null) : {}, + links = [], + // Hash of multi-edges. Used to track ids of edges between same nodes + multiEdges = {}, + nodesCount = 0, + suspendEvents = 0, - var api = { - /** - * Upsates forces acting on a spring - */ - update : function (spring) { - var body1 = spring.from, - body2 = spring.to, - length = spring.length < 0 ? options.springLength : spring.length, - dx = body2.pos.x - body1.pos.x, - dy = body2.pos.y - body1.pos.y, - r = Math.sqrt(dx * dx + dy * dy); - - if (r === 0) { - dx = (random.nextDouble() - 0.5) / 50; - dy = (random.nextDouble() - 0.5) / 50; - r = Math.sqrt(dx * dx + dy * dy); - } - - var d = r - length; - var coeff = ((!spring.coeff || spring.coeff < 0) ? options.springCoeff : spring.coeff) * d / r * spring.weight; - - body1.force.x += coeff * dx; - body1.force.y += coeff * dy; - - body2.force.x -= coeff * dx; - body2.force.y -= coeff * dy; - } - }; - - expose(options, api, ['springCoeff', 'springLength']); - return api; -} - -},{"ngraph.expose":15,"ngraph.merge":24,"ngraph.random":25}],15:[function(require,module,exports){ -module.exports = exposeProperties; - -/** - * Augments `target` object with getter/setter functions, which modify settings - * - * @example - * var target = {}; - * exposeProperties({ age: 42}, target); - * target.age(); // returns 42 - * target.age(24); // make age 24; - * - * var filteredTarget = {}; - * exposeProperties({ age: 42, name: 'John'}, filteredTarget, ['name']); - * filteredTarget.name(); // returns 'John' - * filteredTarget.age === undefined; // true - */ -function exposeProperties(settings, target, filter) { - var needsFilter = Object.prototype.toString.call(filter) === '[object Array]'; - if (needsFilter) { - for (var i = 0; i < filter.length; ++i) { - augment(settings, target, filter[i]); - } - } else { - for (var key in settings) { - augment(settings, target, key); - } - } -} - -function augment(source, target, key) { - if (source.hasOwnProperty(key)) { - if (typeof target[key] === 'function') { - // this accessor is already defined. Ignore it - return; - } - target[key] = function (value) { - if (value !== undefined) { - source[key] = value; - return target; - } - return source[key]; - } - } -} - -},{}],16:[function(require,module,exports){ -module.exports = { - Body: Body, - Vector2d: Vector2d, - Body3d: Body3d, - Vector3d: Vector3d -}; - -function Body(x, y) { - this.pos = new Vector2d(x, y); - this.prevPos = new Vector2d(x, y); - this.force = new Vector2d(); - this.velocity = new Vector2d(); - this.mass = 1; -} - -Body.prototype.setPosition = function (x, y) { - this.prevPos.x = this.pos.x = x; - this.prevPos.y = this.pos.y = y; -}; - -function Vector2d(x, y) { - if (x && typeof x !== 'number') { - // could be another vector - this.x = typeof x.x === 'number' ? x.x : 0; - this.y = typeof x.y === 'number' ? x.y : 0; - } else { - this.x = typeof x === 'number' ? x : 0; - this.y = typeof y === 'number' ? y : 0; - } -} - -Vector2d.prototype.reset = function () { - this.x = this.y = 0; -}; - -function Body3d(x, y, z) { - this.pos = new Vector3d(x, y, z); - this.prevPos = new Vector3d(x, y, z); - this.force = new Vector3d(); - this.velocity = new Vector3d(); - this.mass = 1; -} - -Body3d.prototype.setPosition = function (x, y, z) { - this.prevPos.x = this.pos.x = x; - this.prevPos.y = this.pos.y = y; - this.prevPos.z = this.pos.z = z; -}; - -function Vector3d(x, y, z) { - if (x && typeof x !== 'number') { - // could be another vector - this.x = typeof x.x === 'number' ? x.x : 0; - this.y = typeof x.y === 'number' ? x.y : 0; - this.z = typeof x.z === 'number' ? x.z : 0; - } else { - this.x = typeof x === 'number' ? x : 0; - this.y = typeof y === 'number' ? y : 0; - this.z = typeof z === 'number' ? z : 0; - } -}; + forEachNode = createNodeIterator(), + createLink = options.uniqueLinkId ? createUniqueLink : createSingleLink, -Vector3d.prototype.reset = function () { - this.x = this.y = this.z = 0; -}; + // Our graph API provides means to listen to graph changes. Users can subscribe + // to be notified about changes in the graph by using `on` method. However + // in some cases they don't use it. To avoid unnecessary memory consumption + // we will not record graph changes until we have at least one subscriber. + // Code below supports this optimization. + // + // Accumulates all changes made during graph updates. + // Each change element contains: + // changeType - one of the strings: 'add', 'remove' or 'update'; + // node - if change is related to node this property is set to changed graph's node; + // link - if change is related to link this property is set to changed graph's link; + changes = [], + recordLinkChange = noop, + recordNodeChange = noop, + enterModification = noop, + exitModification = noop; -},{}],17:[function(require,module,exports){ -/** - * This is Barnes Hut simulation algorithm for 2d case. Implementation - * is highly optimized (avoids recusion and gc pressure) - * - * http://www.cs.princeton.edu/courses/archive/fall03/cs126/assignments/barnes-hut.html - */ + // this is our public API: + var graphPart = { + /** + * Adds node to the graph. If node with given id already exists in the graph + * its data is extended with whatever comes in 'data' argument. + * + * @param nodeId the node's identifier. A string or number is preferred. + * note: If you request options.uniqueLinkId, then node id should not + * contain '👉 '. This will break link identifiers + * @param [data] additional data for the node being added. If node already + * exists its data object is augmented with the new one. + * + * @return {node} The newly added node or node with given id if it already exists. + */ + addNode: addNode, -module.exports = function(options) { - options = options || {}; - options.gravity = typeof options.gravity === 'number' ? options.gravity : -1; - options.theta = typeof options.theta === 'number' ? options.theta : 0.8; + /** + * Adds a link to the graph. The function always create a new + * link between two nodes. If one of the nodes does not exists + * a new node is created. + * + * @param fromId link start node id; + * @param toId link end node id; + * @param [data] additional data to be set on the new link; + * + * @return {link} The newly created link + */ + addLink: addLink, - // we require deterministic randomness here - var random = require('ngraph.random').random(1984), - Node = require('./node'), - InsertStack = require('./insertStack'), - isSamePosition = require('./isSamePosition'); + /** + * Removes link from the graph. If link does not exist does nothing. + * + * @param link - object returned by addLink() or getLinks() methods. + * + * @returns true if link was removed; false otherwise. + */ + removeLink: removeLink, - var gravity = options.gravity, - updateQueue = [], - insertStack = new InsertStack(), - theta = options.theta, + /** + * Removes node with given id from the graph. If node does not exist in the graph + * does nothing. + * + * @param nodeId node's identifier passed to addNode() function. + * + * @returns true if node was removed; false otherwise. + */ + removeNode: removeNode, - nodesCache = [], - currentInCache = 0, - newNode = function() { - // To avoid pressure on GC we reuse nodes. - var node = nodesCache[currentInCache]; - if (node) { - node.quad0 = null; - node.quad1 = null; - node.quad2 = null; - node.quad3 = null; - node.body = null; - node.mass = node.massX = node.massY = 0; - node.left = node.right = node.top = node.bottom = 0; - } else { - node = new Node(); - nodesCache[currentInCache] = node; - } + /** + * Gets node with given identifier. If node does not exist undefined value is returned. + * + * @param nodeId requested node identifier; + * + * @return {node} in with requested identifier or undefined if no such node exists. + */ + getNode: getNode, - ++currentInCache; - return node; + /** + * Gets number of nodes in this graph. + * + * @return number of nodes in the graph. + */ + getNodesCount: function() { + return nodesCount; }, - root = newNode(), - - // Inserts body to the tree - insert = function(newBody) { - insertStack.reset(); - insertStack.push(root, newBody); - - while (!insertStack.isEmpty()) { - var stackItem = insertStack.pop(), - node = stackItem.node, - body = stackItem.body; - - if (!node.body) { - // This is internal node. Update the total mass of the node and center-of-mass. - var x = body.pos.x; - var y = body.pos.y; - node.mass = node.mass + body.mass; - node.massX = node.massX + body.mass * x; - node.massY = node.massY + body.mass * y; - - // Recursively insert the body in the appropriate quadrant. - // But first find the appropriate quadrant. - var quadIdx = 0, // Assume we are in the 0's quad. - left = node.left, - right = (node.right + left) / 2, - top = node.top, - bottom = (node.bottom + top) / 2; - - if (x > right) { // somewhere in the eastern part. - quadIdx = quadIdx + 1; - var oldLeft = left; - left = right; - right = right + (right - oldLeft); - } - if (y > bottom) { // and in south. - quadIdx = quadIdx + 2; - var oldTop = top; - top = bottom; - bottom = bottom + (bottom - oldTop); - } - - var child = getChild(node, quadIdx); - if (!child) { - // The node is internal but this quadrant is not taken. Add - // subnode to it. - child = newNode(); - child.left = left; - child.top = top; - child.right = right; - child.bottom = bottom; - child.body = body; - - setChild(node, quadIdx, child); - } else { - // continue searching in this quadrant. - insertStack.push(child, body); - } - } else { - // We are trying to add to the leaf node. - // We have to convert current leaf into internal node - // and continue adding two nodes. - var oldBody = node.body; - node.body = null; // internal nodes do not cary bodies - - if (isSamePosition(oldBody.pos, body.pos)) { - // Prevent infinite subdivision by bumping one node - // anywhere in this quadrant - var retriesCount = 3; - do { - var offset = random.nextDouble(); - var dx = (node.right - node.left) * offset; - var dy = (node.bottom - node.top) * offset; - - oldBody.pos.x = node.left + dx; - oldBody.pos.y = node.top + dy; - retriesCount -= 1; - // Make sure we don't bump it out of the box. If we do, next iteration should fix it - } while (retriesCount > 0 && isSamePosition(oldBody.pos, body.pos)); - - if (retriesCount === 0 && isSamePosition(oldBody.pos, body.pos)) { - // This is very bad, we ran out of precision. - // if we do not return from the method we'll get into - // infinite loop here. So we sacrifice correctness of layout, and keep the app running - // Next layout iteration should get larger bounding box in the first step and fix this - return; - } - } - // Next iteration should subdivide node further. - insertStack.push(node, oldBody); - insertStack.push(node, body); - } - } + /** + * Gets total number of links in the graph. + */ + getLinksCount: function() { + return links.length; }, - update = function(sourceBody) { - var queue = updateQueue, - v, - dx, - dy, - r, fx = 0, - fy = 0, - queueLength = 1, - shiftIdx = 0, - pushIdx = 1; - - queue[0] = root; - - while (queueLength) { - var node = queue[shiftIdx], - body = node.body; - - queueLength -= 1; - shiftIdx += 1; - var differentBody = (body !== sourceBody); - if (body && differentBody) { - // If the current node is a leaf node (and it is not source body), - // calculate the force exerted by the current node on body, and add this - // amount to body's net force. - dx = body.pos.x - sourceBody.pos.x; - dy = body.pos.y - sourceBody.pos.y; - r = Math.sqrt(dx * dx + dy * dy); - - if (r === 0) { - // Poor man's protection against zero distance. - dx = (random.nextDouble() - 0.5) / 50; - dy = (random.nextDouble() - 0.5) / 50; - r = Math.sqrt(dx * dx + dy * dy); - } - - // This is standard gravition force calculation but we divide - // by r^3 to save two operations when normalizing force vector. - v = gravity * body.mass * sourceBody.mass / (r * r * r); - fx += v * dx; - fy += v * dy; - } else if (differentBody) { - // Otherwise, calculate the ratio s / r, where s is the width of the region - // represented by the internal node, and r is the distance between the body - // and the node's center-of-mass - dx = node.massX / node.mass - sourceBody.pos.x; - dy = node.massY / node.mass - sourceBody.pos.y; - r = Math.sqrt(dx * dx + dy * dy); - - if (r === 0) { - // Sorry about code duplucation. I don't want to create many functions - // right away. Just want to see performance first. - dx = (random.nextDouble() - 0.5) / 50; - dy = (random.nextDouble() - 0.5) / 50; - r = Math.sqrt(dx * dx + dy * dy); - } - // If s / r < θ, treat this internal node as a single body, and calculate the - // force it exerts on sourceBody, and add this amount to sourceBody's net force. - if ((node.right - node.left) / r < theta) { - // in the if statement above we consider node's width only - // because the region was squarified during tree creation. - // Thus there is no difference between using width or height. - v = gravity * node.mass * sourceBody.mass / (r * r * r); - fx += v * dx; - fy += v * dy; - } else { - // Otherwise, run the procedure recursively on each of the current node's children. - - // I intentionally unfolded this loop, to save several CPU cycles. - if (node.quad0) { - queue[pushIdx] = node.quad0; - queueLength += 1; - pushIdx += 1; - } - if (node.quad1) { - queue[pushIdx] = node.quad1; - queueLength += 1; - pushIdx += 1; - } - if (node.quad2) { - queue[pushIdx] = node.quad2; - queueLength += 1; - pushIdx += 1; - } - if (node.quad3) { - queue[pushIdx] = node.quad3; - queueLength += 1; - pushIdx += 1; - } - } - } - } - - sourceBody.force.x += fx; - sourceBody.force.y += fy; - }, + /** + * Gets all links (inbound and outbound) from the node with given id. + * If node with given id is not found null is returned. + * + * @param nodeId requested node identifier. + * + * @return Array of links from and to requested node if such node exists; + * otherwise null is returned. + */ + getLinks: getLinks, - insertBodies = function(bodies) { - var x1 = Number.MAX_VALUE, - y1 = Number.MAX_VALUE, - x2 = Number.MIN_VALUE, - y2 = Number.MIN_VALUE, - i, - max = bodies.length; + /** + * Invokes callback on each node of the graph. + * + * @param {Function(node)} callback Function to be invoked. The function + * is passed one argument: visited node. + */ + forEachNode: forEachNode, - // To reduce quad tree depth we are looking for exact bounding box of all particles. - i = max; - while (i--) { - var x = bodies[i].pos.x; - var y = bodies[i].pos.y; - if (x < x1) { - x1 = x; - } - if (x > x2) { - x2 = x; - } - if (y < y1) { - y1 = y; - } - if (y > y2) { - y2 = y; - } - } + /** + * Invokes callback on every linked (adjacent) node to the given one. + * + * @param nodeId Identifier of the requested node. + * @param {Function(node, link)} callback Function to be called on all linked nodes. + * The function is passed two parameters: adjacent node and link object itself. + * @param oriented if true graph treated as oriented. + */ + forEachLinkedNode: forEachLinkedNode, - // Squarify the bounds. - var dx = x2 - x1, - dy = y2 - y1; - if (dx > dy) { - y2 = y1 + dx; - } else { - x2 = x1 + dy; - } + /** + * Enumerates all links in the graph + * + * @param {Function(link)} callback Function to be called on all links in the graph. + * The function is passed one parameter: graph's link object. + * + * Link object contains at least the following fields: + * fromId - node id where link starts; + * toId - node id where link ends, + * data - additional data passed to graph.addLink() method. + */ + forEachLink: forEachLink, - currentInCache = 0; - root = newNode(); - root.left = x1; - root.right = x2; - root.top = y1; - root.bottom = y2; + /** + * Suspend all notifications about graph changes until + * endUpdate is called. + */ + beginUpdate: enterModification, - i = max - 1; - if (i > 0) { - root.body = bodies[i]; - } - while (i--) { - insert(bodies[i], root); - } - }; + /** + * Resumes all notifications about graph changes and fires + * graph 'changed' event in case there are any pending changes. + */ + endUpdate: exitModification, - return { - insertBodies: insertBodies, - updateBodyForce: update, - options: function(newOptions) { - if (newOptions) { - if (typeof newOptions.gravity === 'number') { - gravity = newOptions.gravity; - } - if (typeof newOptions.theta === 'number') { - theta = newOptions.theta; - } + /** + * Removes all nodes and links from the graph. + */ + clear: clear, - return this; - } + /** + * Detects whether there is a link between two nodes. + * Operation complexity is O(n) where n - number of links of a node. + * NOTE: this function is synonim for getLink() + * + * @returns link if there is one. null otherwise. + */ + hasLink: getLink, - return { - gravity: gravity, - theta: theta - }; - } + /** + * Gets an edge between two nodes. + * Operation complexity is O(n) where n - number of links of a node. + * + * @param {string} fromId link start identifier + * @param {string} toId link end identifier + * + * @returns link if there is one. null otherwise. + */ + getLink: getLink }; -}; - -function getChild(node, idx) { - if (idx === 0) return node.quad0; - if (idx === 1) return node.quad1; - if (idx === 2) return node.quad2; - if (idx === 3) return node.quad3; - return null; -} -function setChild(node, idx, child) { - if (idx === 0) node.quad0 = child; - else if (idx === 1) node.quad1 = child; - else if (idx === 2) node.quad2 = child; - else if (idx === 3) node.quad3 = child; -} + // this will add `on()` and `fire()` methods. + eventify(graphPart); -},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":25}],18:[function(require,module,exports){ -module.exports = InsertStack; + monitorSubscribers(); -/** - * Our implmentation of QuadTree is non-recursive to avoid GC hit - * This data structure represent stack of elements - * which we are trying to insert into quad tree. - */ -function InsertStack () { - this.stack = []; - this.popIdx = 0; -} + return graphPart; -InsertStack.prototype = { - isEmpty: function() { - return this.popIdx === 0; - }, - push: function (node, body) { - var item = this.stack[this.popIdx]; - if (!item) { - // we are trying to avoid memory pressue: create new element - // only when absolutely necessary - this.stack[this.popIdx] = new InsertStackElement(node, body); - } else { - item.node = node; - item.body = body; - } - ++this.popIdx; - }, - pop: function () { - if (this.popIdx > 0) { - return this.stack[--this.popIdx]; - } - }, - reset: function () { - this.popIdx = 0; - } -}; + function monitorSubscribers() { + var realOn = graphPart.on; -function InsertStackElement(node, body) { - this.node = node; // QuadTree node - this.body = body; // physical body which needs to be inserted to node -} + // replace real `on` with our temporary on, which will trigger change + // modification monitoring: + graphPart.on = on; -},{}],19:[function(require,module,exports){ -module.exports = function isSamePosition(point1, point2) { - var dx = Math.abs(point1.x - point2.x); - var dy = Math.abs(point1.y - point2.y); + function on() { + // now it's time to start tracking stuff: + graphPart.beginUpdate = enterModification = enterModificationReal; + graphPart.endUpdate = exitModification = exitModificationReal; + recordLinkChange = recordLinkChangeReal; + recordNodeChange = recordNodeChangeReal; - return (dx < 1e-8 && dy < 1e-8); -}; + // this will replace current `on` method with real pub/sub from `eventify`. + graphPart.on = realOn; + // delegate to real `on` handler: + return realOn.apply(graphPart, arguments); + } + } -},{}],20:[function(require,module,exports){ -/** - * Internal data structure to represent 2D QuadTree node - */ -module.exports = function Node() { - // body stored inside this node. In quad tree only leaf nodes (by construction) - // contain boides: - this.body = null; + function recordLinkChangeReal(link, changeType) { + changes.push({ + link: link, + changeType: changeType + }); + } - // Child nodes are stored in quads. Each quad is presented by number: - // 0 | 1 - // ----- - // 2 | 3 - this.quad0 = null; - this.quad1 = null; - this.quad2 = null; - this.quad3 = null; + function recordNodeChangeReal(node, changeType) { + changes.push({ + node: node, + changeType: changeType + }); + } - // Total mass of current node - this.mass = 0; + function addNode(nodeId, data) { + if (nodeId === undefined) { + throw new Error('Invalid node identifier'); + } - // Center of mass coordinates - this.massX = 0; - this.massY = 0; + enterModification(); - // bounding box coordinates - this.left = 0; - this.top = 0; - this.bottom = 0; - this.right = 0; -}; + var node = getNode(nodeId); + if (!node) { + // TODO: Should I check for 👉 here? + node = new Node(nodeId); + nodesCount++; + recordNodeChange(node, 'add'); + } else { + recordNodeChange(node, 'update'); + } -},{}],21:[function(require,module,exports){ -module.exports = load; + node.data = data; -var createGraph = require('ngraph.graph'); + nodes[nodeId] = node; -function load(jsonGraph, nodeTransform, linkTransform) { - var stored; - nodeTransform = nodeTransform || id; - linkTransform = linkTransform || id; - if (typeof jsonGraph === 'string') { - stored = JSON.parse(jsonGraph); - } else { - stored = jsonGraph; + exitModification(); + return node; } - var graph = createGraph(), - i; - - if (stored.links === undefined || stored.nodes === undefined) { - throw new Error('Cannot load graph without links and nodes'); + function getNode(nodeId) { + return nodes[nodeId]; } - for (i = 0; i < stored.nodes.length; ++i) { - var parsedNode = nodeTransform(stored.nodes[i]); - if (!parsedNode.hasOwnProperty('id')) { - throw new Error('Graph node format is invalid: Node id is missing'); + function removeNode(nodeId) { + var node = getNode(nodeId); + if (!node) { + return false; } - graph.addNode(parsedNode.id, parsedNode.data); - } + enterModification(); - for (i = 0; i < stored.links.length; ++i) { - var link = linkTransform(stored.links[i]); - if (!link.hasOwnProperty('fromId') || !link.hasOwnProperty('toId')) { - throw new Error('Graph link format is invalid. Both fromId and toId are required'); + while (node.links.length) { + var link = node.links[0]; + removeLink(link); } - graph.addLink(link.fromId, link.toId, link.data); + delete nodes[nodeId]; + nodesCount--; + + recordNodeChange(node, 'remove'); + + exitModification(); + + return true; } - return graph; -} -function id(x) { return x; } + function addLink(fromId, toId, data) { + enterModification(); -},{"ngraph.graph":23}],22:[function(require,module,exports){ -module.exports = { - ladder: ladder, - complete: complete, - completeBipartite: completeBipartite, - balancedBinTree: balancedBinTree, - path: path, - circularLadder: circularLadder, - grid: grid, - grid3: grid3, - noLinks: noLinks, - wattsStrogatz: wattsStrogatz -}; + var fromNode = getNode(fromId) || addNode(fromId); + var toNode = getNode(toId) || addNode(toId); -var createGraph = require('ngraph.graph'); + var link = createLink(fromId, toId, data); -function ladder(n) { -/** - * Ladder graph is a graph in form of ladder - * @param {Number} n Represents number of steps in the ladder - */ - if (!n || n < 0) { - throw new Error("Invalid number of nodes"); - } + links.push(link); - var g = createGraph(), - i; + // TODO: this is not cool. On large graphs potentially would consume more memory. + fromNode.links.push(link); + if (fromId !== toId) { + // make sure we are not duplicating links for self-loops + toNode.links.push(link); + } - for (i = 0; i < n - 1; ++i) { - g.addLink(i, i + 1); - // first row - g.addLink(n + i, n + i + 1); - // second row - g.addLink(i, n + i); - // ladder's step + recordLinkChange(link, 'add'); + + exitModification(); + + return link; } - g.addLink(n - 1, 2 * n - 1); - // last step in the ladder; + function createSingleLink(fromId, toId, data) { + var linkId = fromId.toString() + toId.toString(); + return new Link(fromId, toId, data, linkId); + } - return g; -} + function createUniqueLink(fromId, toId, data) { + var linkId = fromId.toString() + '👉 ' + toId.toString(); + var isMultiEdge = multiEdges.hasOwnProperty(linkId); + if (isMultiEdge || getLink(fromId, toId)) { + if (!isMultiEdge) { + multiEdges[linkId] = 0; + } + linkId += '@' + (++multiEdges[linkId]); + } -function circularLadder(n) { -/** - * Circular ladder with n steps. - * - * @param {Number} n of steps in the ladder. - */ - if (!n || n < 0) { - throw new Error("Invalid number of nodes"); + return new Link(fromId, toId, data, linkId); + } + + function getLinks(nodeId) { + var node = getNode(nodeId); + return node ? node.links : null; + } + + function removeLink(link) { + if (!link) { + return false; + } + var idx = indexOfElementInArray(link, links); + if (idx < 0) { + return false; } - var g = ladder(n); + enterModification(); - g.addLink(0, n - 1); - g.addLink(n, 2 * n - 1); - return g; -} + links.splice(idx, 1); -function complete(n) { -/** - * Complete graph Kn. - * - * @param {Number} n represents number of nodes in the complete graph. - */ - if (!n || n < 1) { - throw new Error("At least two nodes are expected for complete graph"); - } + var fromNode = getNode(link.fromId); + var toNode = getNode(link.toId); - var g = createGraph(), - i, - j; + if (fromNode) { + idx = indexOfElementInArray(link, fromNode.links); + if (idx >= 0) { + fromNode.links.splice(idx, 1); + } + } - for (i = 0; i < n; ++i) { - for (j = i + 1; j < n; ++j) { - if (i !== j) { - g.addLink(i, j); + if (toNode) { + idx = indexOfElementInArray(link, toNode.links); + if (idx >= 0) { + toNode.links.splice(idx, 1); } } - } - return g; -} + recordLinkChange(link, 'remove'); -function completeBipartite (n, m) { -/** - * Complete bipartite graph K n,m. Each node in the - * first partition is connected to all nodes in the second partition. - * - * @param {Number} n represents number of nodes in the first graph partition - * @param {Number} m represents number of nodes in the second graph partition - */ - if (!n || !m || n < 0 || m < 0) { - throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0"); + exitModification(); + + return true; } - var g = createGraph(), - i, j; + function getLink(fromNodeId, toNodeId) { + // TODO: Use sorted links to speed this up + var node = getNode(fromNodeId), + i; + if (!node) { + return null; + } - for (i = 0; i < n; ++i) { - for (j = n; j < n + m; ++j) { - g.addLink(i, j); + for (i = 0; i < node.links.length; ++i) { + var link = node.links[i]; + if (link.fromId === fromNodeId && link.toId === toNodeId) { + return link; + } } + + return null; // no link. } - return g; -} + function clear() { + enterModification(); + forEachNode(function(node) { + removeNode(node.id); + }); + exitModification(); + } -function path(n) { -/** - * Path graph with n steps. - * - * @param {Number} n number of nodes in the path - */ - if (!n || n < 0) { - throw new Error("Invalid number of nodes"); + function forEachLink(callback) { + var i, length; + if (typeof callback === 'function') { + for (i = 0, length = links.length; i < length; ++i) { + callback(links[i]); + } + } } - var g = createGraph(), - i; + function forEachLinkedNode(nodeId, callback, oriented) { + var node = getNode(nodeId); - g.addNode(0); + if (node && node.links && typeof callback === 'function') { + if (oriented) { + return forEachOrientedLink(node.links, nodeId, callback); + } else { + return forEachNonOrientedLink(node.links, nodeId, callback); + } + } + } + + function forEachNonOrientedLink(links, nodeId, callback) { + var quitFast; + for (var i = 0; i < links.length; ++i) { + var link = links[i]; + var linkedNodeId = link.fromId === nodeId ? link.toId : link.fromId; - for (i = 1; i < n; ++i) { - g.addLink(i - 1, i); + quitFast = callback(nodes[linkedNodeId], link); + if (quitFast) { + return true; // Client does not need more iterations. Break now. + } + } } - return g; -} + function forEachOrientedLink(links, nodeId, callback) { + var quitFast; + for (var i = 0; i < links.length; ++i) { + var link = links[i]; + if (link.fromId === nodeId) { + quitFast = callback(nodes[link.toId], link); + if (quitFast) { + return true; // Client does not need more iterations. Break now. + } + } + } + } + // we will not fire anything until users of this library explicitly call `on()` + // method. + function noop() {} -function grid(n, m) { -/** - * Grid graph with n rows and m columns. - * - * @param {Number} n of rows in the graph. - * @param {Number} m of columns in the graph. - */ - if (n < 1 || m < 1) { - throw new Error("Invalid number of nodes in grid graph"); - } - var g = createGraph(), - i, - j; - if (n === 1 && m === 1) { - g.addNode(0); - return g; + // Enter, Exit modification allows bulk graph updates without firing events. + function enterModificationReal() { + suspendEvents += 1; } - for (i = 0; i < n; ++i) { - for (j = 0; j < m; ++j) { - var node = i + j * n; - if (i > 0) { g.addLink(node, i - 1 + j * n); } - if (j > 0) { g.addLink(node, i + (j - 1) * n); } + function exitModificationReal() { + suspendEvents -= 1; + if (suspendEvents === 0 && changes.length > 0) { + graphPart.fire('changed', changes); + changes.length = 0; } } - return g; -} - -function grid3(n, m, z) { -/** - * 3D grid with n rows and m columns and z levels. - * - * @param {Number} n of rows in the graph. - * @param {Number} m of columns in the graph. - * @param {Number} z of levels in the graph. - */ - if (n < 1 || m < 1 || z < 1) { - throw new Error("Invalid number of nodes in grid3 graph"); + function createNodeIterator() { + // Object.keys iterator is 1.3x faster than `for in` loop. + // See `https://github.com/anvaka/ngraph.graph/tree/bench-for-in-vs-obj-keys` + // branch for perf test + return Object.keys ? objectKeysIterator : forInIterator; } - var g = createGraph(), - i, j, k; - if (n === 1 && m === 1 && z === 1) { - g.addNode(0); - return g; - } + function objectKeysIterator(callback) { + if (typeof callback !== 'function') { + return; + } - for (k = 0; k < z; ++k) { - for (i = 0; i < n; ++i) { - for (j = 0; j < m; ++j) { - var level = k * n * m; - var node = i + j * n + level; - if (i > 0) { g.addLink(node, i - 1 + j * n + level); } - if (j > 0) { g.addLink(node, i + (j - 1) * n + level); } - if (k > 0) { g.addLink(node, i + j * n + (k - 1) * n * m ); } + var keys = Object.keys(nodes); + for (var i = 0; i < keys.length; ++i) { + if (callback(nodes[keys[i]])) { + return true; // client doesn't want to proceed. Return. } } } - return g; -} + function forInIterator(callback) { + if (typeof callback !== 'function') { + return; + } + var node; -function balancedBinTree(n) { -/** - * Balanced binary tree with n levels. - * - * @param {Number} n of levels in the binary tree - */ - if (n < 0) { - throw new Error("Invalid number of nodes in balanced tree"); + for (node in nodes) { + if (callback(nodes[node])) { + return true; // client doesn't want to proceed. Return. + } + } } - var g = createGraph(), - count = Math.pow(2, n), - level; +} - if (n === 0) { - g.addNode(1); +// need this for old browsers. Should this be a separate module? +function indexOfElementInArray(element, array) { + if (array.indexOf) { + return array.indexOf(element); } - for (level = 1; level < count; ++level) { - var root = level, - left = root * 2, - right = root * 2 + 1; + var len = array.length, + i; - g.addLink(root, left); - g.addLink(root, right); + for (i = 0; i < len; i += 1) { + if (array[i] === element) { + return i; + } } - return g; + return -1; } -function noLinks(n) { /** - * Graph with no links - * - * @param {Number} n of nodes in the graph + * Internal structure to represent node; */ - if (n < 0) { - throw new Error("Number of nodes shoul be >= 0"); - } +function Node(id) { + this.id = id; + this.links = []; + this.data = null; +} - var g = createGraph(), i; - for (i = 0; i < n; ++i) { - g.addNode(i); - } - return g; +/** + * Internal structure to represent links; + */ +function Link(fromId, toId, data, id) { + this.fromId = fromId; + this.toId = toId; + this.data = data; + this.id = id; } -function wattsStrogatz(n, k, p, seed) { +},{"ngraph.events":7}],13:[function(require,module,exports){ +module.exports = merge; + /** - * Watts-Strogatz small-world graph. + * Augments `target` with properties in `options`. Does not override + * target's properties if they are defined and matches expected type in + * options * - * @param {Number} n The number of nodes - * @param {Number} k Each node is connected to k nearest neighbors in ring topology - * @param {Number} p The probability of rewiring each edge - - * @see https://github.com/networkx/networkx/blob/master/networkx/generators/random_graphs.py + * @returns {Object} merged object */ - if (k >= n) throw new Error('Choose smaller `k`. It cannot be larger than number of nodes `n`'); +function merge(target, options) { + var key; + if (!target) { target = {}; } + if (options) { + for (key in options) { + if (options.hasOwnProperty(key)) { + var targetHasIt = target.hasOwnProperty(key), + optionsValueType = typeof options[key], + shouldReplace = !targetHasIt || (typeof target[key] !== optionsValueType); + if (shouldReplace) { + target[key] = options[key]; + } else if (optionsValueType === 'object') { + // go deep, don't care about loops here, we are simple API!: + target[key] = merge(target[key], options[key]); + } + } + } + } - var random = require('ngraph.random').random(seed || 42); + return target; +} - var g = createGraph(), i, to; - for (i = 0; i < n; ++i) { - g.addNode(i); - } +},{}],14:[function(require,module,exports){ +module.exports = { + Body: Body, + Vector2d: Vector2d, + Body3d: Body3d, + Vector3d: Vector3d +}; - // connect each node to k/2 neighbors - var neighborsSize = Math.floor(k/2 + 1); - for (var j = 1; j < neighborsSize; ++j) { - for (i = 0; i < n; ++i) { - to = (j + i) % n; - g.addLink(i, to); - } - } +function Body(x, y) { + this.pos = new Vector2d(x, y); + this.prevPos = new Vector2d(x, y); + this.force = new Vector2d(); + this.velocity = new Vector2d(); + this.mass = 1; +} - // rewire edges from each node - // loop over all nodes in order (label) and neighbors in order (distance) - // no self loops or multiple edges allowed - for (j = 1; j < neighborsSize; ++j) { - for (i = 0; i < n; ++i) { - if (random.nextDouble() < p) { - var from = i; - to = (j + i) % n; +Body.prototype.setPosition = function (x, y) { + this.prevPos.x = this.pos.x = x; + this.prevPos.y = this.pos.y = y; +}; - var newTo = random.next(n); - var needsRewire = (newTo === from || g.hasLink(from, newTo)); - if (needsRewire && g.getLinks(from).length === n - 1) { - // we cannot rewire this node, it has too many links. - continue; - } - // Enforce no self-loops or multiple edges - while (needsRewire) { - newTo = random.next(n); - needsRewire = (newTo === from || g.hasLink(from, newTo)); - } - var link = g.hasLink(from, to); - g.removeLink(link); - g.addLink(from, newTo); - } - } +function Vector2d(x, y) { + if (x && typeof x !== 'number') { + // could be another vector + this.x = typeof x.x === 'number' ? x.x : 0; + this.y = typeof x.y === 'number' ? x.y : 0; + } else { + this.x = typeof x === 'number' ? x : 0; + this.y = typeof y === 'number' ? y : 0; } +} - return g; +Vector2d.prototype.reset = function () { + this.x = this.y = 0; +}; + +function Body3d(x, y, z) { + this.pos = new Vector3d(x, y, z); + this.prevPos = new Vector3d(x, y, z); + this.force = new Vector3d(); + this.velocity = new Vector3d(); + this.mass = 1; } -},{"ngraph.graph":23,"ngraph.random":25}],23:[function(require,module,exports){ -/** - * @fileOverview Contains definition of the core graph object. - */ +Body3d.prototype.setPosition = function (x, y, z) { + this.prevPos.x = this.pos.x = x; + this.prevPos.y = this.pos.y = y; + this.prevPos.z = this.pos.z = z; +}; -/** - * @example - * var graph = require('ngraph.graph')(); - * graph.addNode(1); // graph has one node. - * graph.addLink(2, 3); // now graph contains three nodes and one link. - * - */ -module.exports = createGraph; +function Vector3d(x, y, z) { + if (x && typeof x !== 'number') { + // could be another vector + this.x = typeof x.x === 'number' ? x.x : 0; + this.y = typeof x.y === 'number' ? x.y : 0; + this.z = typeof x.z === 'number' ? x.z : 0; + } else { + this.x = typeof x === 'number' ? x : 0; + this.y = typeof y === 'number' ? y : 0; + this.z = typeof z === 'number' ? z : 0; + } +}; -var eventify = require('ngraph.events'); +Vector3d.prototype.reset = function () { + this.x = this.y = this.z = 0; +}; +},{}],15:[function(require,module,exports){ /** - * Creates a new graph + * Manages a simulation of physical forces acting on bodies and springs. */ -function createGraph(options) { - // Graph structure is maintained as dictionary of nodes - // and array of links. Each node has 'links' property which - // hold all links related to that node. And general links - // array is used to speed up all links enumeration. This is inefficient - // in terms of memory, but simplifies coding. - options = options || {}; - if (options.uniqueLinkId === undefined) { - // Request each link id to be unique between same nodes. This negatively - // impacts `addLink()` performance (O(n), where n - number of edges of each - // vertex), but makes operations with multigraphs more accessible. - options.uniqueLinkId = true; - } +module.exports = physicsSimulator; - var nodes = typeof Object.create === 'function' ? Object.create(null) : {}, - links = [], - // Hash of multi-edges. Used to track ids of edges between same nodes - multiEdges = {}, - nodesCount = 0, - suspendEvents = 0, +function physicsSimulator(settings) { + var Spring = require('./lib/spring'); + var expose = require('ngraph.expose'); + var merge = require('ngraph.merge'); - forEachNode = createNodeIterator(), - createLink = options.uniqueLinkId ? createUniqueLink : createSingleLink, + settings = merge(settings, { + /** + * Ideal length for links (springs in physical model). + */ + springLength: 30, - // Our graph API provides means to listen to graph changes. Users can subscribe - // to be notified about changes in the graph by using `on` method. However - // in some cases they don't use it. To avoid unnecessary memory consumption - // we will not record graph changes until we have at least one subscriber. - // Code below supports this optimization. - // - // Accumulates all changes made during graph updates. - // Each change element contains: - // changeType - one of the strings: 'add', 'remove' or 'update'; - // node - if change is related to node this property is set to changed graph's node; - // link - if change is related to link this property is set to changed graph's link; - changes = [], - recordLinkChange = noop, - recordNodeChange = noop, - enterModification = noop, - exitModification = noop; + /** + * Hook's law coefficient. 1 - solid spring. + */ + springCoeff: 0.0008, - // this is our public API: - var graphPart = { - /** - * Adds node to the graph. If node with given id already exists in the graph - * its data is extended with whatever comes in 'data' argument. - * - * @param nodeId the node's identifier. A string or number is preferred. - * note: If you request options.uniqueLinkId, then node id should not - * contain '👉 '. This will break link identifiers - * @param [data] additional data for the node being added. If node already - * exists its data object is augmented with the new one. - * - * @return {node} The newly added node or node with given id if it already exists. - */ - addNode: addNode, + /** + * Coulomb's law coefficient. It's used to repel nodes thus should be negative + * if you make it positive nodes start attract each other :). + */ + gravity: -1.2, - /** - * Adds a link to the graph. The function always create a new - * link between two nodes. If one of the nodes does not exists - * a new node is created. - * - * @param fromId link start node id; - * @param toId link end node id; - * @param [data] additional data to be set on the new link; - * - * @return {link} The newly created link - */ - addLink: addLink, + /** + * Theta coefficient from Barnes Hut simulation. Ranged between (0, 1). + * The closer it's to 1 the more nodes algorithm will have to go through. + * Setting it to one makes Barnes Hut simulation no different from + * brute-force forces calculation (each node is considered). + */ + theta: 0.8, + + /** + * Drag force coefficient. Used to slow down system, thus should be less than 1. + * The closer it is to 0 the less tight system will be. + */ + dragCoeff: 0.02, + + /** + * Default time step (dt) for forces integration + */ + timeStep : 20, + + /** + * Maximum movement of the system which can be considered as stabilized + */ + stableThreshold: 0.009 + }); + // We allow clients to override basic factory methods: + var createQuadTree = settings.createQuadTree || require('ngraph.quadtreebh'); + var createBounds = settings.createBounds || require('./lib/bounds'); + var createDragForce = settings.createDragForce || require('./lib/dragForce'); + var createSpringForce = settings.createSpringForce || require('./lib/springForce'); + var integrate = settings.integrator || require('./lib/eulerIntegrator'); + var createBody = settings.createBody || require('./lib/createBody'); + + var bodies = [], // Bodies in this simulation. + springs = [], // Springs in this simulation. + quadTree = createQuadTree(settings), + bounds = createBounds(bodies, settings), + springForce = createSpringForce(settings), + dragForce = createDragForce(settings); + + var publicApi = { /** - * Removes link from the graph. If link does not exist does nothing. - * - * @param link - object returned by addLink() or getLinks() methods. + * Array of bodies, registered with current simulator * - * @returns true if link was removed; false otherwise. + * Note: To add new body, use addBody() method. This property is only + * exposed for testing/performance purposes. */ - removeLink: removeLink, + bodies: bodies, /** - * Removes node with given id from the graph. If node does not exist in the graph - * does nothing. - * - * @param nodeId node's identifier passed to addNode() function. + * Array of springs, registered with current simulator * - * @returns true if node was removed; false otherwise. + * Note: To add new spring, use addSpring() method. This property is only + * exposed for testing/performance purposes. */ - removeNode: removeNode, + springs: springs, /** - * Gets node with given identifier. If node does not exist undefined value is returned. - * - * @param nodeId requested node identifier; - * - * @return {node} in with requested identifier or undefined if no such node exists. + * Returns settings with which current simulator was initialized */ - getNode: getNode, + settings: settings, /** - * Gets number of nodes in this graph. + * Performs one step of force simulation. * - * @return number of nodes in the graph. + * @returns {boolean} true if system is considered stable; False otherwise. */ - getNodesCount: function() { - return nodesCount; - }, + step: function () { + accumulateForces(); + var totalMovement = integrate(bodies, settings.timeStep); - /** - * Gets total number of links in the graph. - */ - getLinksCount: function() { - return links.length; + bounds.update(); + + return totalMovement < settings.stableThreshold; }, /** - * Gets all links (inbound and outbound) from the node with given id. - * If node with given id is not found null is returned. + * Adds body to the system * - * @param nodeId requested node identifier. + * @param {ngraph.physics.primitives.Body} body physical body * - * @return Array of links from and to requested node if such node exists; - * otherwise null is returned. + * @returns {ngraph.physics.primitives.Body} added body */ - getLinks: getLinks, + addBody: function (body) { + if (!body) { + throw new Error('Body is required'); + } + bodies.push(body); - /** - * Invokes callback on each node of the graph. - * - * @param {Function(node)} callback Function to be invoked. The function - * is passed one argument: visited node. - */ - forEachNode: forEachNode, + return body; + }, /** - * Invokes callback on every linked (adjacent) node to the given one. + * Adds body to the system at given position * - * @param nodeId Identifier of the requested node. - * @param {Function(node, link)} callback Function to be called on all linked nodes. - * The function is passed two parameters: adjacent node and link object itself. - * @param oriented if true graph treated as oriented. + * @param {Object} pos position of a body + * + * @returns {ngraph.physics.primitives.Body} added body */ - forEachLinkedNode: forEachLinkedNode, + addBodyAt: function (pos) { + if (!pos) { + throw new Error('Body position is required'); + } + var body = createBody(pos); + bodies.push(body); + + return body; + }, /** - * Enumerates all links in the graph + * Removes body from the system * - * @param {Function(link)} callback Function to be called on all links in the graph. - * The function is passed one parameter: graph's link object. + * @param {ngraph.physics.primitives.Body} body to remove * - * Link object contains at least the following fields: - * fromId - node id where link starts; - * toId - node id where link ends, - * data - additional data passed to graph.addLink() method. + * @returns {Boolean} true if body found and removed. falsy otherwise; */ - forEachLink: forEachLink, + removeBody: function (body) { + if (!body) { return; } - /** - * Suspend all notifications about graph changes until - * endUpdate is called. - */ - beginUpdate: enterModification, + var idx = bodies.indexOf(body); + if (idx < 0) { return; } - /** - * Resumes all notifications about graph changes and fires - * graph 'changed' event in case there are any pending changes. - */ - endUpdate: exitModification, + bodies.splice(idx, 1); + if (bodies.length === 0) { + bounds.reset(); + } + return true; + }, /** - * Removes all nodes and links from the graph. + * Adds a spring to this simulation. + * + * @returns {Object} - a handle for a spring. If you want to later remove + * spring pass it to removeSpring() method. */ - clear: clear, + addSpring: function (body1, body2, springLength, springWeight, springCoefficient) { + if (!body1 || !body2) { + throw new Error('Cannot add null spring to force simulator'); + } + + if (typeof springLength !== 'number') { + springLength = -1; // assume global configuration + } + + var spring = new Spring(body1, body2, springLength, springCoefficient >= 0 ? springCoefficient : -1, springWeight); + springs.push(spring); + + // TODO: could mark simulator as dirty. + return spring; + }, /** - * Detects whether there is a link between two nodes. - * Operation complexity is O(n) where n - number of links of a node. - * NOTE: this function is synonim for getLink() + * Removes spring from the system * - * @returns link if there is one. null otherwise. + * @param {Object} spring to remove. Spring is an object returned by addSpring + * + * @returns {Boolean} true if spring found and removed. falsy otherwise; */ - hasLink: getLink, + removeSpring: function (spring) { + if (!spring) { return; } + var idx = springs.indexOf(spring); + if (idx > -1) { + springs.splice(idx, 1); + return true; + } + }, + + getBestNewBodyPosition: function (neighbors) { + return bounds.getBestNewPosition(neighbors); + }, /** - * Gets an edge between two nodes. - * Operation complexity is O(n) where n - number of links of a node. - * - * @param {string} fromId link start identifier - * @param {string} toId link end identifier - * - * @returns link if there is one. null otherwise. + * Returns bounding box which covers all bodies */ - getLink: getLink - }; + getBBox: function () { + return bounds.box; + }, - // this will add `on()` and `fire()` methods. - eventify(graphPart); + gravity: function (value) { + if (value !== undefined) { + settings.gravity = value; + quadTree.options({gravity: value}); + return this; + } else { + return settings.gravity; + } + }, - monitorSubscribers(); + theta: function (value) { + if (value !== undefined) { + settings.theta = value; + quadTree.options({theta: value}); + return this; + } else { + return settings.theta; + } + } + }; - return graphPart; + // allow settings modification via public API: + expose(settings, publicApi); - function monitorSubscribers() { - var realOn = graphPart.on; + return publicApi; - // replace real `on` with our temporary on, which will trigger change - // modification monitoring: - graphPart.on = on; + function accumulateForces() { + // Accumulate forces acting on bodies. + var body, + i = bodies.length; - function on() { - // now it's time to start tracking stuff: - graphPart.beginUpdate = enterModification = enterModificationReal; - graphPart.endUpdate = exitModification = exitModificationReal; - recordLinkChange = recordLinkChangeReal; - recordNodeChange = recordNodeChangeReal; + if (i) { + // only add bodies if there the array is not empty: + quadTree.insertBodies(bodies); // performance: O(n * log n) + while (i--) { + body = bodies[i]; + // If body is pinned there is no point updating its forces - it should + // never move: + if (!body.isPinned) { + body.force.reset(); - // this will replace current `on` method with real pub/sub from `eventify`. - graphPart.on = realOn; - // delegate to real `on` handler: - return realOn.apply(graphPart, arguments); + quadTree.updateBodyForce(body); + dragForce.update(body); + } + } + } + + i = springs.length; + while(i--) { + springForce.update(springs[i]); } } +}; - function recordLinkChangeReal(link, changeType) { - changes.push({ - link: link, - changeType: changeType - }); +},{"./lib/bounds":16,"./lib/createBody":17,"./lib/dragForce":18,"./lib/eulerIntegrator":19,"./lib/spring":20,"./lib/springForce":21,"ngraph.expose":8,"ngraph.merge":13,"ngraph.quadtreebh":22}],16:[function(require,module,exports){ +module.exports = function (bodies, settings) { + var random = require('ngraph.random').random(42); + var boundingBox = { x1: 0, y1: 0, x2: 0, y2: 0 }; + + return { + box: boundingBox, + + update: updateBoundingBox, + + reset : function () { + boundingBox.x1 = boundingBox.y1 = 0; + boundingBox.x2 = boundingBox.y2 = 0; + }, + + getBestNewPosition: function (neighbors) { + var graphRect = boundingBox; + + var baseX = 0, baseY = 0; + + if (neighbors.length) { + for (var i = 0; i < neighbors.length; ++i) { + baseX += neighbors[i].pos.x; + baseY += neighbors[i].pos.y; + } + + baseX /= neighbors.length; + baseY /= neighbors.length; + } else { + baseX = (graphRect.x1 + graphRect.x2) / 2; + baseY = (graphRect.y1 + graphRect.y2) / 2; + } + + var springLength = settings.springLength; + return { + x: baseX + random.next(springLength) - springLength / 2, + y: baseY + random.next(springLength) - springLength / 2 + }; + } + }; + + function updateBoundingBox() { + var i = bodies.length; + if (i === 0) { return; } // don't have to wory here. + + var x1 = Number.MAX_VALUE, + y1 = Number.MAX_VALUE, + x2 = Number.MIN_VALUE, + y2 = Number.MIN_VALUE; + + while(i--) { + // this is O(n), could it be done faster with quadtree? + // how about pinned nodes? + var body = bodies[i]; + if (body.isPinned) { + body.pos.x = body.prevPos.x; + body.pos.y = body.prevPos.y; + } else { + body.prevPos.x = body.pos.x; + body.prevPos.y = body.pos.y; + } + if (body.pos.x < x1) { + x1 = body.pos.x; + } + if (body.pos.x > x2) { + x2 = body.pos.x; + } + if (body.pos.y < y1) { + y1 = body.pos.y; + } + if (body.pos.y > y2) { + y2 = body.pos.y; + } + } + + boundingBox.x1 = x1; + boundingBox.x2 = x2; + boundingBox.y1 = y1; + boundingBox.y2 = y2; } +} + +},{"ngraph.random":26}],17:[function(require,module,exports){ +var physics = require('ngraph.physics.primitives'); + +module.exports = function(pos) { + return new physics.Body(pos); +} + +},{"ngraph.physics.primitives":14}],18:[function(require,module,exports){ +/** + * Represents drag force, which reduces force value on each step by given + * coefficient. + * + * @param {Object} options for the drag force + * @param {Number=} options.dragCoeff drag force coefficient. 0.1 by default + */ +module.exports = function (options) { + var merge = require('ngraph.merge'), + expose = require('ngraph.expose'); - function recordNodeChangeReal(node, changeType) { - changes.push({ - node: node, - changeType: changeType - }); - } + options = merge(options, { + dragCoeff: 0.02 + }); - function addNode(nodeId, data) { - if (nodeId === undefined) { - throw new Error('Invalid node identifier'); + var api = { + update : function (body) { + body.force.x -= options.dragCoeff * body.velocity.x; + body.force.y -= options.dragCoeff * body.velocity.y; } + }; - enterModification(); + // let easy access to dragCoeff: + expose(options, api, ['dragCoeff']); - var node = getNode(nodeId); - if (!node) { - // TODO: Should I check for 👉 here? - node = new Node(nodeId); - nodesCount++; - recordNodeChange(node, 'add'); - } else { - recordNodeChange(node, 'update'); - } + return api; +}; - node.data = data; +},{"ngraph.expose":8,"ngraph.merge":13}],19:[function(require,module,exports){ +/** + * Performs forces integration, using given timestep. Uses Euler method to solve + * differential equation (http://en.wikipedia.org/wiki/Euler_method ). + * + * @returns {Number} squared distance of total position updates. + */ - nodes[nodeId] = node; +module.exports = integrate; - exitModification(); - return node; - } +function integrate(bodies, timeStep) { + var dx = 0, tx = 0, + dy = 0, ty = 0, + i, + max = bodies.length; - function getNode(nodeId) { - return nodes[nodeId]; - } + for (i = 0; i < max; ++i) { + var body = bodies[i], + coeff = timeStep / body.mass; - function removeNode(nodeId) { - var node = getNode(nodeId); - if (!node) { - return false; + body.velocity.x += coeff * body.force.x; + body.velocity.y += coeff * body.force.y; + var vx = body.velocity.x, + vy = body.velocity.y, + v = Math.sqrt(vx * vx + vy * vy); + + if (v > 1) { + body.velocity.x = vx / v; + body.velocity.y = vy / v; } - enterModification(); + dx = timeStep * body.velocity.x; + dy = timeStep * body.velocity.y; - while (node.links.length) { - var link = node.links[0]; - removeLink(link); - } + body.pos.x += dx; + body.pos.y += dy; - delete nodes[nodeId]; - nodesCount--; + tx += Math.abs(dx); ty += Math.abs(dy); + } - recordNodeChange(node, 'remove'); + return (tx * tx + ty * ty)/bodies.length; +} - exitModification(); +},{}],20:[function(require,module,exports){ +module.exports = Spring; - return true; - } +/** + * Represents a physical spring. Spring connects two bodies, has rest length + * stiffness coefficient and optional weight + */ +function Spring(fromBody, toBody, length, coeff, weight) { + this.from = fromBody; + this.to = toBody; + this.length = length; + this.coeff = coeff; + this.weight = typeof weight === 'number' ? weight : 1; +}; - function addLink(fromId, toId, data) { - enterModification(); +},{}],21:[function(require,module,exports){ +/** + * Represents spring force, which updates forces acting on two bodies, conntected + * by a spring. + * + * @param {Object} options for the spring force + * @param {Number=} options.springCoeff spring force coefficient. + * @param {Number=} options.springLength desired length of a spring at rest. + */ +module.exports = function (options) { + var merge = require('ngraph.merge'); + var random = require('ngraph.random').random(42); + var expose = require('ngraph.expose'); - var fromNode = getNode(fromId) || addNode(fromId); - var toNode = getNode(toId) || addNode(toId); + options = merge(options, { + springCoeff: 0.0002, + springLength: 80 + }); - var link = createLink(fromId, toId, data); + var api = { + /** + * Upsates forces acting on a spring + */ + update : function (spring) { + var body1 = spring.from, + body2 = spring.to, + length = spring.length < 0 ? options.springLength : spring.length, + dx = body2.pos.x - body1.pos.x, + dy = body2.pos.y - body1.pos.y, + r = Math.sqrt(dx * dx + dy * dy); - links.push(link); + if (r === 0) { + dx = (random.nextDouble() - 0.5) / 50; + dy = (random.nextDouble() - 0.5) / 50; + r = Math.sqrt(dx * dx + dy * dy); + } - // TODO: this is not cool. On large graphs potentially would consume more memory. - fromNode.links.push(link); - if (fromId !== toId) { - // make sure we are not duplicating links for self-loops - toNode.links.push(link); + var d = r - length; + var coeff = ((!spring.coeff || spring.coeff < 0) ? options.springCoeff : spring.coeff) * d / r * spring.weight; + + body1.force.x += coeff * dx; + body1.force.y += coeff * dy; + + body2.force.x -= coeff * dx; + body2.force.y -= coeff * dy; } + }; - recordLinkChange(link, 'add'); + expose(options, api, ['springCoeff', 'springLength']); + return api; +} - exitModification(); +},{"ngraph.expose":8,"ngraph.merge":13,"ngraph.random":26}],22:[function(require,module,exports){ +/** + * This is Barnes Hut simulation algorithm for 2d case. Implementation + * is highly optimized (avoids recusion and gc pressure) + * + * http://www.cs.princeton.edu/courses/archive/fall03/cs126/assignments/barnes-hut.html + */ - return link; - } +module.exports = function(options) { + options = options || {}; + options.gravity = typeof options.gravity === 'number' ? options.gravity : -1; + options.theta = typeof options.theta === 'number' ? options.theta : 0.8; - function createSingleLink(fromId, toId, data) { - var linkId = fromId.toString() + toId.toString(); - return new Link(fromId, toId, data, linkId); - } + // we require deterministic randomness here + var random = require('ngraph.random').random(1984), + Node = require('./node'), + InsertStack = require('./insertStack'), + isSamePosition = require('./isSamePosition'); - function createUniqueLink(fromId, toId, data) { - var linkId = fromId.toString() + '👉 ' + toId.toString(); - var isMultiEdge = multiEdges.hasOwnProperty(linkId); - if (isMultiEdge || getLink(fromId, toId)) { - if (!isMultiEdge) { - multiEdges[linkId] = 0; - } - linkId += '@' + (++multiEdges[linkId]); - } + var gravity = options.gravity, + updateQueue = [], + insertStack = new InsertStack(), + theta = options.theta, - return new Link(fromId, toId, data, linkId); - } + nodesCache = [], + currentInCache = 0, + newNode = function() { + // To avoid pressure on GC we reuse nodes. + var node = nodesCache[currentInCache]; + if (node) { + node.quad0 = null; + node.quad1 = null; + node.quad2 = null; + node.quad3 = null; + node.body = null; + node.mass = node.massX = node.massY = 0; + node.left = node.right = node.top = node.bottom = 0; + } else { + node = new Node(); + nodesCache[currentInCache] = node; + } - function getLinks(nodeId) { - var node = getNode(nodeId); - return node ? node.links : null; - } + ++currentInCache; + return node; + }, - function removeLink(link) { - if (!link) { - return false; - } - var idx = indexOfElementInArray(link, links); - if (idx < 0) { - return false; - } + root = newNode(), - enterModification(); + // Inserts body to the tree + insert = function(newBody) { + insertStack.reset(); + insertStack.push(root, newBody); - links.splice(idx, 1); + while (!insertStack.isEmpty()) { + var stackItem = insertStack.pop(), + node = stackItem.node, + body = stackItem.body; - var fromNode = getNode(link.fromId); - var toNode = getNode(link.toId); + if (!node.body) { + // This is internal node. Update the total mass of the node and center-of-mass. + var x = body.pos.x; + var y = body.pos.y; + node.mass = node.mass + body.mass; + node.massX = node.massX + body.mass * x; + node.massY = node.massY + body.mass * y; - if (fromNode) { - idx = indexOfElementInArray(link, fromNode.links); - if (idx >= 0) { - fromNode.links.splice(idx, 1); - } - } + // Recursively insert the body in the appropriate quadrant. + // But first find the appropriate quadrant. + var quadIdx = 0, // Assume we are in the 0's quad. + left = node.left, + right = (node.right + left) / 2, + top = node.top, + bottom = (node.bottom + top) / 2; - if (toNode) { - idx = indexOfElementInArray(link, toNode.links); - if (idx >= 0) { - toNode.links.splice(idx, 1); - } - } + if (x > right) { // somewhere in the eastern part. + quadIdx = quadIdx + 1; + var oldLeft = left; + left = right; + right = right + (right - oldLeft); + } + if (y > bottom) { // and in south. + quadIdx = quadIdx + 2; + var oldTop = top; + top = bottom; + bottom = bottom + (bottom - oldTop); + } - recordLinkChange(link, 'remove'); + var child = getChild(node, quadIdx); + if (!child) { + // The node is internal but this quadrant is not taken. Add + // subnode to it. + child = newNode(); + child.left = left; + child.top = top; + child.right = right; + child.bottom = bottom; + child.body = body; - exitModification(); + setChild(node, quadIdx, child); + } else { + // continue searching in this quadrant. + insertStack.push(child, body); + } + } else { + // We are trying to add to the leaf node. + // We have to convert current leaf into internal node + // and continue adding two nodes. + var oldBody = node.body; + node.body = null; // internal nodes do not cary bodies - return true; - } + if (isSamePosition(oldBody.pos, body.pos)) { + // Prevent infinite subdivision by bumping one node + // anywhere in this quadrant + var retriesCount = 3; + do { + var offset = random.nextDouble(); + var dx = (node.right - node.left) * offset; + var dy = (node.bottom - node.top) * offset; - function getLink(fromNodeId, toNodeId) { - // TODO: Use sorted links to speed this up - var node = getNode(fromNodeId), - i; - if (!node) { - return null; - } + oldBody.pos.x = node.left + dx; + oldBody.pos.y = node.top + dy; + retriesCount -= 1; + // Make sure we don't bump it out of the box. If we do, next iteration should fix it + } while (retriesCount > 0 && isSamePosition(oldBody.pos, body.pos)); - for (i = 0; i < node.links.length; ++i) { - var link = node.links[i]; - if (link.fromId === fromNodeId && link.toId === toNodeId) { - return link; + if (retriesCount === 0 && isSamePosition(oldBody.pos, body.pos)) { + // This is very bad, we ran out of precision. + // if we do not return from the method we'll get into + // infinite loop here. So we sacrifice correctness of layout, and keep the app running + // Next layout iteration should get larger bounding box in the first step and fix this + return; + } + } + // Next iteration should subdivide node further. + insertStack.push(node, oldBody); + insertStack.push(node, body); + } } - } + }, - return null; // no link. - } + update = function(sourceBody) { + var queue = updateQueue, + v, + dx, + dy, + r, fx = 0, + fy = 0, + queueLength = 1, + shiftIdx = 0, + pushIdx = 1; - function clear() { - enterModification(); - forEachNode(function(node) { - removeNode(node.id); - }); - exitModification(); - } + queue[0] = root; - function forEachLink(callback) { - var i, length; - if (typeof callback === 'function') { - for (i = 0, length = links.length; i < length; ++i) { - callback(links[i]); - } - } - } + while (queueLength) { + var node = queue[shiftIdx], + body = node.body; - function forEachLinkedNode(nodeId, callback, oriented) { - var node = getNode(nodeId); + queueLength -= 1; + shiftIdx += 1; + var differentBody = (body !== sourceBody); + if (body && differentBody) { + // If the current node is a leaf node (and it is not source body), + // calculate the force exerted by the current node on body, and add this + // amount to body's net force. + dx = body.pos.x - sourceBody.pos.x; + dy = body.pos.y - sourceBody.pos.y; + r = Math.sqrt(dx * dx + dy * dy); - if (node && node.links && typeof callback === 'function') { - if (oriented) { - return forEachOrientedLink(node.links, nodeId, callback); - } else { - return forEachNonOrientedLink(node.links, nodeId, callback); - } - } - } + if (r === 0) { + // Poor man's protection against zero distance. + dx = (random.nextDouble() - 0.5) / 50; + dy = (random.nextDouble() - 0.5) / 50; + r = Math.sqrt(dx * dx + dy * dy); + } - function forEachNonOrientedLink(links, nodeId, callback) { - var quitFast; - for (var i = 0; i < links.length; ++i) { - var link = links[i]; - var linkedNodeId = link.fromId === nodeId ? link.toId : link.fromId; + // This is standard gravition force calculation but we divide + // by r^3 to save two operations when normalizing force vector. + v = gravity * body.mass * sourceBody.mass / (r * r * r); + fx += v * dx; + fy += v * dy; + } else if (differentBody) { + // Otherwise, calculate the ratio s / r, where s is the width of the region + // represented by the internal node, and r is the distance between the body + // and the node's center-of-mass + dx = node.massX / node.mass - sourceBody.pos.x; + dy = node.massY / node.mass - sourceBody.pos.y; + r = Math.sqrt(dx * dx + dy * dy); - quitFast = callback(nodes[linkedNodeId], link); - if (quitFast) { - return true; // Client does not need more iterations. Break now. - } - } - } + if (r === 0) { + // Sorry about code duplucation. I don't want to create many functions + // right away. Just want to see performance first. + dx = (random.nextDouble() - 0.5) / 50; + dy = (random.nextDouble() - 0.5) / 50; + r = Math.sqrt(dx * dx + dy * dy); + } + // If s / r < θ, treat this internal node as a single body, and calculate the + // force it exerts on sourceBody, and add this amount to sourceBody's net force. + if ((node.right - node.left) / r < theta) { + // in the if statement above we consider node's width only + // because the region was squarified during tree creation. + // Thus there is no difference between using width or height. + v = gravity * node.mass * sourceBody.mass / (r * r * r); + fx += v * dx; + fy += v * dy; + } else { + // Otherwise, run the procedure recursively on each of the current node's children. - function forEachOrientedLink(links, nodeId, callback) { - var quitFast; - for (var i = 0; i < links.length; ++i) { - var link = links[i]; - if (link.fromId === nodeId) { - quitFast = callback(nodes[link.toId], link); - if (quitFast) { - return true; // Client does not need more iterations. Break now. + // I intentionally unfolded this loop, to save several CPU cycles. + if (node.quad0) { + queue[pushIdx] = node.quad0; + queueLength += 1; + pushIdx += 1; + } + if (node.quad1) { + queue[pushIdx] = node.quad1; + queueLength += 1; + pushIdx += 1; + } + if (node.quad2) { + queue[pushIdx] = node.quad2; + queueLength += 1; + pushIdx += 1; + } + if (node.quad3) { + queue[pushIdx] = node.quad3; + queueLength += 1; + pushIdx += 1; + } + } } } - } - } - - // we will not fire anything until users of this library explicitly call `on()` - // method. - function noop() {} - - // Enter, Exit modification allows bulk graph updates without firing events. - function enterModificationReal() { - suspendEvents += 1; - } - function exitModificationReal() { - suspendEvents -= 1; - if (suspendEvents === 0 && changes.length > 0) { - graphPart.fire('changed', changes); - changes.length = 0; - } - } + sourceBody.force.x += fx; + sourceBody.force.y += fy; + }, - function createNodeIterator() { - // Object.keys iterator is 1.3x faster than `for in` loop. - // See `https://github.com/anvaka/ngraph.graph/tree/bench-for-in-vs-obj-keys` - // branch for perf test - return Object.keys ? objectKeysIterator : forInIterator; - } + insertBodies = function(bodies) { + var x1 = Number.MAX_VALUE, + y1 = Number.MAX_VALUE, + x2 = Number.MIN_VALUE, + y2 = Number.MIN_VALUE, + i, + max = bodies.length; - function objectKeysIterator(callback) { - if (typeof callback !== 'function') { - return; - } + // To reduce quad tree depth we are looking for exact bounding box of all particles. + i = max; + while (i--) { + var x = bodies[i].pos.x; + var y = bodies[i].pos.y; + if (x < x1) { + x1 = x; + } + if (x > x2) { + x2 = x; + } + if (y < y1) { + y1 = y; + } + if (y > y2) { + y2 = y; + } + } - var keys = Object.keys(nodes); - for (var i = 0; i < keys.length; ++i) { - if (callback(nodes[keys[i]])) { - return true; // client doesn't want to proceed. Return. + // Squarify the bounds. + var dx = x2 - x1, + dy = y2 - y1; + if (dx > dy) { + y2 = y1 + dx; + } else { + x2 = x1 + dy; } - } - } - function forInIterator(callback) { - if (typeof callback !== 'function') { - return; - } - var node; + currentInCache = 0; + root = newNode(); + root.left = x1; + root.right = x2; + root.top = y1; + root.bottom = y2; - for (node in nodes) { - if (callback(nodes[node])) { - return true; // client doesn't want to proceed. Return. + i = max - 1; + if (i > 0) { + root.body = bodies[i]; } - } - } -} + while (i--) { + insert(bodies[i], root); + } + }; -// need this for old browsers. Should this be a separate module? -function indexOfElementInArray(element, array) { - if (array.indexOf) { - return array.indexOf(element); - } + return { + insertBodies: insertBodies, + updateBodyForce: update, + options: function(newOptions) { + if (newOptions) { + if (typeof newOptions.gravity === 'number') { + gravity = newOptions.gravity; + } + if (typeof newOptions.theta === 'number') { + theta = newOptions.theta; + } - var len = array.length, - i; + return this; + } - for (i = 0; i < len; i += 1) { - if (array[i] === element) { - return i; + return { + gravity: gravity, + theta: theta + }; } - } + }; +}; - return -1; +function getChild(node, idx) { + if (idx === 0) return node.quad0; + if (idx === 1) return node.quad1; + if (idx === 2) return node.quad2; + if (idx === 3) return node.quad3; + return null; } -/** - * Internal structure to represent node; - */ -function Node(id) { - this.id = id; - this.links = []; - this.data = null; +function setChild(node, idx, child) { + if (idx === 0) node.quad0 = child; + else if (idx === 1) node.quad1 = child; + else if (idx === 2) node.quad2 = child; + else if (idx === 3) node.quad3 = child; } +},{"./insertStack":23,"./isSamePosition":24,"./node":25,"ngraph.random":26}],23:[function(require,module,exports){ +module.exports = InsertStack; /** - * Internal structure to represent links; + * Our implmentation of QuadTree is non-recursive to avoid GC hit + * This data structure represent stack of elements + * which we are trying to insert into quad tree. */ -function Link(fromId, toId, data, id) { - this.fromId = fromId; - this.toId = toId; - this.data = data; - this.id = id; +function InsertStack () { + this.stack = []; + this.popIdx = 0; } -},{"ngraph.events":6}],24:[function(require,module,exports){ -module.exports = merge; - -/** - * Augments `target` with properties in `options`. Does not override - * target's properties if they are defined and matches expected type in - * options - * - * @returns {Object} merged object - */ -function merge(target, options) { - var key; - if (!target) { target = {}; } - if (options) { - for (key in options) { - if (options.hasOwnProperty(key)) { - var targetHasIt = target.hasOwnProperty(key), - optionsValueType = typeof options[key], - shouldReplace = !targetHasIt || (typeof target[key] !== optionsValueType); - - if (shouldReplace) { - target[key] = options[key]; - } else if (optionsValueType === 'object') { - // go deep, don't care about loops here, we are simple API!: - target[key] = merge(target[key], options[key]); +InsertStack.prototype = { + isEmpty: function() { + return this.popIdx === 0; + }, + push: function (node, body) { + var item = this.stack[this.popIdx]; + if (!item) { + // we are trying to avoid memory pressue: create new element + // only when absolutely necessary + this.stack[this.popIdx] = new InsertStackElement(node, body); + } else { + item.node = node; + item.body = body; } - } + ++this.popIdx; + }, + pop: function () { + if (this.popIdx > 0) { + return this.stack[--this.popIdx]; + } + }, + reset: function () { + this.popIdx = 0; } - } +}; - return target; +function InsertStackElement(node, body) { + this.node = node; // QuadTree node + this.body = body; // physical body which needs to be inserted to node } +},{}],24:[function(require,module,exports){ +module.exports = function isSamePosition(point1, point2) { + var dx = Math.abs(point1.x - point2.x); + var dy = Math.abs(point1.y - point2.y); + + return (dx < 1e-8 && dy < 1e-8); +}; + },{}],25:[function(require,module,exports){ +/** + * Internal data structure to represent 2D QuadTree node + */ +module.exports = function Node() { + // body stored inside this node. In quad tree only leaf nodes (by construction) + // contain boides: + this.body = null; + + // Child nodes are stored in quads. Each quad is presented by number: + // 0 | 1 + // ----- + // 2 | 3 + this.quad0 = null; + this.quad1 = null; + this.quad2 = null; + this.quad3 = null; + + // Total mass of current node + this.mass = 0; + + // Center of mass coordinates + this.massX = 0; + this.massY = 0; + + // bounding box coordinates + this.left = 0; + this.top = 0; + this.bottom = 0; + this.right = 0; +}; + +},{}],26:[function(require,module,exports){ module.exports = { random: random, randomIterator: randomIterator @@ -2816,7 +2864,7 @@ function randomIterator(array, customRandom) { }; } -},{}],26:[function(require,module,exports){ +},{}],27:[function(require,module,exports){ module.exports = save; function save(graph, customNodeTransform, customLinkTransform) { @@ -2872,7 +2920,7 @@ function save(graph, customNodeTransform, customLinkTransform) { } } -},{}],27:[function(require,module,exports){ +},{}],28:[function(require,module,exports){ module.exports = svg; svg.compile = require('./lib/compile'); @@ -2985,7 +3033,7 @@ function augment(element) { } } -},{"./lib/compile":28,"./lib/compile_template":29,"add-event-listener":31}],28:[function(require,module,exports){ +},{"./lib/compile":29,"./lib/compile_template":30,"add-event-listener":2}],29:[function(require,module,exports){ var parser = require('./domparser.js'); var svg = require('../'); @@ -3013,7 +3061,7 @@ function addNamespaces(text) { } } -},{"../":27,"./domparser.js":30}],29:[function(require,module,exports){ +},{"../":28,"./domparser.js":31}],30:[function(require,module,exports){ module.exports = template; var BINDING_EXPR = /{{(.+?)}}/; @@ -3107,7 +3155,7 @@ function bindTextContent(element, allBindings) { } } -},{}],30:[function(require,module,exports){ +},{}],31:[function(require,module,exports){ module.exports = createDomparser(); function createDomparser() { @@ -3123,54 +3171,6 @@ function fail() { throw new Error('DOMParser is not supported by this platform. Please open issue here https://github.com/anvaka/simplesvg'); } -},{}],31:[function(require,module,exports){ -addEventListener.removeEventListener = removeEventListener -addEventListener.addEventListener = addEventListener - -module.exports = addEventListener - -var Events = null - -function addEventListener(el, eventName, listener, useCapture) { - Events = Events || ( - document.addEventListener ? - {add: stdAttach, rm: stdDetach} : - {add: oldIEAttach, rm: oldIEDetach} - ) - - return Events.add(el, eventName, listener, useCapture) -} - -function removeEventListener(el, eventName, listener, useCapture) { - Events = Events || ( - document.addEventListener ? - {add: stdAttach, rm: stdDetach} : - {add: oldIEAttach, rm: oldIEDetach} - ) - - return Events.rm(el, eventName, listener, useCapture) -} - -function stdAttach(el, eventName, listener, useCapture) { - el.addEventListener(eventName, listener, useCapture) -} - -function stdDetach(el, eventName, listener, useCapture) { - el.removeEventListener(eventName, listener, useCapture) -} - -function oldIEAttach(el, eventName, listener, useCapture) { - if(useCapture) { - throw new Error('cannot useCapture in oldIE') - } - - el.attachEvent('on' + eventName, listener) -} - -function oldIEDetach(el, eventName, listener, useCapture) { - el.detachEvent('on' + eventName, listener) -} - },{}],32:[function(require,module,exports){ var centrality = require('ngraph.centrality'); @@ -3209,7 +3209,7 @@ function toVivaGraphCentralityFormat(centrality) { } } -},{"ngraph.centrality":3}],33:[function(require,module,exports){ +},{"ngraph.centrality":4}],33:[function(require,module,exports){ /** * @fileOverview Contains collection of primitive operations under graph. * @@ -3846,7 +3846,7 @@ function constant(graph, userSettings) { } } -},{"../Utils/rect.js":45,"ngraph.merge":24,"ngraph.random":25}],38:[function(require,module,exports){ +},{"../Utils/rect.js":45,"ngraph.merge":13,"ngraph.random":26}],38:[function(require,module,exports){ /** * This module provides compatibility layer with 0.6.x library. It will be * removed in the next version @@ -3891,7 +3891,7 @@ function backwardCompatibleEvents(g) { } } -},{"ngraph.events":6}],39:[function(require,module,exports){ +},{"ngraph.events":7}],39:[function(require,module,exports){ module.exports = browserInfo(); function browserInfo() { @@ -3997,7 +3997,7 @@ function intersectRect(left, top, right, bottom, x1, y1, x2, y2) { intersect(right, top, left, top, x1, y1, x2, y2); } -},{"gintersect":2}],44:[function(require,module,exports){ +},{"gintersect":3}],44:[function(require,module,exports){ module.exports = createNullEvents(); function createNullEvents() { @@ -4582,6 +4582,7 @@ function renderer(graph, settings) { graphics.translateRel(offset.x, offset.y); renderGraph(); + publicEvents.fire('drag', offset); }); } @@ -4624,7 +4625,7 @@ function renderer(graph, settings) { } } -},{"../Input/domInputManager.js":34,"../Input/dragndrop.js":35,"../Utils/getDimensions.js":42,"../Utils/timer.js":46,"../Utils/windowEvents.js":47,"./svgGraphics.js":49,"ngraph.events":6,"ngraph.forcelayout":7}],49:[function(require,module,exports){ +},{"../Input/domInputManager.js":34,"../Input/dragndrop.js":35,"../Utils/getDimensions.js":42,"../Utils/timer.js":46,"../Utils/windowEvents.js":47,"./svgGraphics.js":49,"ngraph.events":7,"ngraph.forcelayout":9}],49:[function(require,module,exports){ /** * @fileOverview Defines a graph renderer that uses SVG based drawings. * @@ -4982,7 +4983,7 @@ function svgGraphics() { } } -},{"../Input/domInputManager.js":34,"ngraph.events":6,"simplesvg":27}],50:[function(require,module,exports){ +},{"../Input/domInputManager.js":34,"ngraph.events":7,"simplesvg":28}],50:[function(require,module,exports){ /** * @fileOverview Defines a graph renderer that uses WebGL based drawings. * @@ -5564,7 +5565,7 @@ function webglGraphics(options) { return graphics; } -},{"../Input/webglInputManager.js":36,"../WebGL/webglLine.js":58,"../WebGL/webglLinkProgram.js":59,"../WebGL/webglNodeProgram.js":60,"../WebGL/webglSquare.js":61,"ngraph.events":6,"ngraph.merge":24}],51:[function(require,module,exports){ +},{"../Input/webglInputManager.js":36,"../WebGL/webglLine.js":58,"../WebGL/webglLinkProgram.js":59,"../WebGL/webglNodeProgram.js":60,"../WebGL/webglSquare.js":61,"ngraph.events":7,"ngraph.merge":13}],51:[function(require,module,exports){ module.exports = parseColor; function parseColor(color) { diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index ee186a0..b926426 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=s*d-f*c,0===y?null:(x=0>y?-y/2:y/2,x=0,w=c*p-d*l,b.x=(0>w?w-x:w+x)/y,w=f*l-s*p,b.y=(0>w?w-x:w+x)/y,b)))}n.exports=r},{}],3:[function(e,n,t){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":4,"./src/degree.js":5}],4:[function(e,n,t){function r(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;ir;++r){var o=e.links[r],i=o.fromId!==e.id?w[o.fromId]:w[o.toId];i&&i.pos&&n.push(i)}return n}function v(e){var n=w[e];n.mass=m(e)}function g(e){return e&&(e.isPinned||e.data&&e.data.isPinned)}function h(e){var n=w[e];return n||(f(e),n=w[e]),n}function m(e){return 1+n.getLinks(e).length/3}if(!n)throw new Error("Graph structure cannot be undefined");var y=e("ngraph.physics.simulator"),x=y(t),w="function"==typeof Object.create?Object.create(null):{},b={},E=x.settings.springTransform||o;s(),a();var L={step:function(){return x.step()},getNodePosition:function(e){return h(e).pos},setNodePosition:function(e){var n=h(e);n.setPosition.apply(n,Array.prototype.slice.call(arguments,1))},getLinkPosition:function(e){var n=b[e];return n?{from:n.from.pos,to:n.to.pos}:void 0},getGraphRect:function(){return x.getBBox()},pinNode:function(e,n){var t=h(e.id);t.isPinned=!!n},isNodePinned:function(e){return h(e.id).isPinned},dispose:function(){n.off("changed",u)},getBody:i,getSpring:r,simulator:x};return L}function o(){}n.exports=r,n.exports.simulator=e("ngraph.physics.simulator")},{"ngraph.physics.simulator":8}],8:[function(e,n,t){function r(n){function t(){var e,n=l.length;if(n)for(v.insertBodies(l);n--;)e=l[n],e.isPinned||(e.force.reset(),v.updateBodyForce(e),m.update(e));for(n=p.length;n--;)h.update(p[n])}var r=e("./lib/spring"),o=e("ngraph.expose"),i=e("ngraph.merge");n=i(n,{springLength:30,springCoeff:8e-4,gravity:-1.2,theta:.8,dragCoeff:.02,timeStep:20,stableThreshold:.009});var a=n.createQuadTree||e("ngraph.quadtreebh"),u=n.createBounds||e("./lib/bounds"),s=n.createDragForce||e("./lib/dragForce"),f=n.createSpringForce||e("./lib/springForce"),c=n.integrator||e("./lib/eulerIntegrator"),d=n.createBody||e("./lib/createBody"),l=[],p=[],v=a(n),g=u(l,n),h=f(n),m=s(n),y={bodies:l,springs:p,settings:n,step:function(){t();var e=c(l,n.timeStep);return g.update(),en))return l.splice(n,1),0===l.length&&g.reset(),!0}},addSpring:function(e,n,t,o,i){if(!e||!n)throw new Error("Cannot add null spring to force simulator");"number"!=typeof t&&(t=-1);var a=new r(e,n,t,i>=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return g.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=r},{"./lib/bounds":9,"./lib/createBody":10,"./lib/dragForce":11,"./lib/eulerIntegrator":12,"./lib/spring":13,"./lib/springForce":14,"ngraph.expose":15,"ngraph.merge":24,"ngraph.quadtreebh":17}],9:[function(e,n,t){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;ut;++t){var s=e[t],f=n/s.mass;s.velocity.x+=f*s.force.x,s.velocity.y+=f*s.force.y;var c=s.velocity.x,d=s.velocity.y,l=Math.sqrt(c*c+d*d);l>1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=r},{}],13:[function(e,n,t){function r(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=r},{}],14:[function(e,n,t){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":15,"ngraph.merge":24,"ngraph.random":25}],15:[function(e,n,t){function r(e,n,t){var r="[object Array]"===Object.prototype.toString.call(t);if(r)for(var i=0;i0&&u(s.pos,a.pos));if(0===f&&u(s.pos,a.pos))return}c.push(i,s),c.push(i,a)}else{var h=a.pos.x,m=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*h,i.massY=i.massY+a.mass*m;var y=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;if(h>w){y+=1;var L=x;x=w,w+=w-L}if(m>E){y+=2;var P=b;b=E,E+=E-P}var N=r(i,y);N?c.push(N,a):(N=v(),N.left=x,N.top=b,N.right=w,N.bottom=E,N.body=a,o(i,y,N))}}},m=function(e){var n,r,o,i,a=f,u=0,c=0,l=1,p=0,v=1;for(a[0]=g;l;){var h=a[p],m=h.body;l-=1,p+=1;var y=m!==e;m&&y?(r=m.pos.x-e.pos.x,o=m.pos.y-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),n=s*m.mass*e.mass/(i*i*i),u+=n*r,c+=n*o):y&&(r=h.massX/h.mass-e.pos.x,o=h.massY/h.mass-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),(h.right-h.left)/iu&&(t=u),u>o&&(o=u),r>s&&(r=s),s>i&&(i=s)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,p=0,g=v(),g.left=t,g.right=o,g.top=r,g.bottom=i,n=a-1,n>0&&(g.body=e[n]);n--;)h(e[n],g)};return{insertBodies:y,updateBodyForce:m,options:function(e){return e?("number"==typeof e.gravity&&(s=e.gravity),"number"==typeof e.theta&&(d=e.theta),this):{gravity:s,theta:d}}}}},{"./insertStack":18,"./isSamePosition":19,"./node":20,"ngraph.random":25}],18:[function(e,n,t){function r(){this.stack=[],this.popIdx=0}function o(e,n){this.node=e,this.body=n}n.exports=r,r.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new o(e,n),++this.popIdx},pop:function(){return this.popIdx>0?this.stack[--this.popIdx]:void 0},reset:function(){this.popIdx=0}}},{}],19:[function(e,n,t){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return 1e-8>t&&1e-8>r}},{}],20:[function(e,n,t){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],21:[function(e,n,t){function r(e,n,t){var r;n=n||o,t=t||o,r="string"==typeof e?JSON.parse(e):e;var a,u=i();if(void 0===r.links||void 0===r.nodes)throw new Error("Cannot load graph without links and nodes");for(a=0;ae)throw new Error("Invalid number of nodes");var n,t=p();for(n=0;e-1>n;++n)t.addLink(n,n+1),t.addLink(e+n,e+n+1),t.addLink(n,e+n);return t.addLink(e-1,2*e-1),t}function o(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n=r(e);return n.addLink(0,e-1),n.addLink(e,2*e-1),n}function i(e){if(!e||1>e)throw new Error("At least two nodes are expected for complete graph");var n,t,r=p();for(n=0;e>n;++n)for(t=n+1;e>t;++t)n!==t&&r.addLink(n,t);return r}function a(e,n){if(!e||!n||0>e||0>n)throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0");var t,r,o=p();for(t=0;e>t;++t)for(r=e;e+n>r;++r)o.addLink(t,r);return o}function u(e){if(!e||0>e)throw new Error("Invalid number of nodes");var n,t=p();for(t.addNode(0),n=1;e>n;++n)t.addLink(n-1,n);return t}function s(e,n){if(1>e||1>n)throw new Error("Invalid number of nodes in grid graph");var t,r,o=p();if(1===e&&1===n)return o.addNode(0),o;for(t=0;e>t;++t)for(r=0;n>r;++r){var i=t+r*e;t>0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function f(e,n,t){if(1>e||1>n||1>t)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=p();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;t>i;++i)for(r=0;e>r;++r)for(o=0;n>o;++o){var u=i*e*n,s=r+o*e+u;r>0&&a.addLink(s,r-1+o*e+u),o>0&&a.addLink(s,r+(o-1)*e+u),i>0&&a.addLink(s,r+o*e+(i-1)*e*n)}return a}function c(e){if(0>e)throw new Error("Invalid number of nodes in balanced tree");var n,t=p(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;r>n;++n){var o=n,i=2*o,a=2*o+1;t.addLink(o,i),t.addLink(o,a)}return t}function d(e){if(0>e)throw new Error("Number of nodes shoul be >= 0");var n,t=p();for(n=0;e>n;++n)t.addNode(n);return t}function l(n,t,r,o){if(t>=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,u=e("ngraph.random").random(o||42),s=p();for(i=0;n>i;++i)s.addNode(i);for(var f=Math.floor(t/2+1),c=1;f>c;++c)for(i=0;n>i;++i)a=(c+i)%n,s.addLink(i,a);for(c=1;f>c;++c)for(i=0;n>i;++i)if(u.nextDouble()n)return!1;B(),_.splice(n,1);var t=f(e.fromId),r=f(e.toId);return t&&(n=o(e,t.links),n>=0&&t.links.splice(n,1)),r&&(n=o(e,r.links),n>=0&&r.links.splice(n,1)),U(e,"remove"),F(),!0}function h(e,n){var t,r=f(e);if(!r)return null;for(t=0;tn;++n)e(_[n])}function x(e,n,t){var r=f(e);return r&&r.links&&"function"==typeof n?t?b(r.links,e,n):w(r.links,e,n):void 0}function w(e,n,t){for(var r,o=0;o0&&(O.fire("changed",M),M.length=0)}function N(){return Object.keys?k:A}function k(e){if("function"==typeof e)for(var n=Object.keys(j),t=0;tt;t+=1)if(n[t]===e)return t;return-1}function i(e){this.id=e,this.links=[],this.data=null}function a(e,n,t,r){this.fromId=e,this.toId=n,this.data=t,this.id=r}n.exports=r;var u=e("ngraph.events")},{"ngraph.events":6}],24:[function(e,n,t){function r(e,n){var t;if(e||(e={}),n)for(t in n)if(n.hasOwnProperty(t)){var o=e.hasOwnProperty(t),i=typeof n[t],a=!o||typeof e[t]!==i;a?e[t]=n[t]:"object"===i&&(e[t]=r(e[t],n[t]))}return e}n.exports=r},{}],25:[function(e,n,t){function r(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function o(e,n){var t=n||r();if("function"!=typeof t.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var r,o,i;for(r=e.length-1;r>0;--r)o=t.next(r+1),i=e[o],e[o]=e[r],e[r]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,r,o;for(n=e.length-1;n>0;--n)r=t.next(n+1),o=e[r],e[r]=e[n],e[n]=o;return e}}}n.exports={random:r,randomIterator:o}},{}],26:[function(e,n,t){function r(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=r},{}],27:[function(e,n,t){function r(e,n){var t=o(e);if(void 0===n)return t;for(var r=Object.keys(n),i=0;it?r=-1:t>v&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},A=function(e){p=!1,o.off("touchmove",k),o.off("touchend",A),o.off("touchcancel",A),c=null,r&&r(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,o.on("touchmove",k),o.on("touchend",A),o.on("touchcancel",A))},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=N(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return P(e),this},release:function(){e.removeEventListener("mousedown",b), -e.removeEventListener("touchstart",_),o.off("mousemove",w),o.off("mouseup",E),o.off("touchmove",k),o.off("touchend",A),o.off("touchcancel",A),P(null)}}}n.exports=r;var o=e("../Utils/documentEvents.js"),i=e("../Utils/browserInfo.js"),a=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":39,"../Utils/documentEvents.js":40,"../Utils/findElementPosition.js":41}],36:[function(e,n,t){function r(e,n){var t=o(n),r=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){r=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(r);var o=i[e.id];return o&&o.onStart&&o.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(r),r=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(r){var t=i[r.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=r;var o=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":57}],37:[function(e,n,t){function r(e,n){function t(e){return d[e]}n=o(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var r=i(n.seed),u=new a(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(e){return{x:r.next(n.maxX),y:r.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"==typeof z?z:!0}function r(){G=G||window.document.body,F=F||i(e,{springLength:80,springCoeff:2e-4}),O=O||a(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||s)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=f(function(){return p()},M)):(X=0,V=0,R=f(p,M)))}function g(){J||(W=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;en,t)})),e.forEachNode(E),T(),e.on("changed",j)}function D(){q=!1,T(),I(),u.off("resize",_),K.off(),R.stop(),e.forEachLink(function(e){n.renderLinks&&b(e)}),e.forEachNode(function(e){L(e),x(e)}),F.dispose(),N()}var M=30;n=n||{};var U,R,B,F=n.layout,O=n.graphics,G=n.container,z=void 0!==n.interactive?n.interactive:!0,q=!1,Y=!0,X=0,V=0,W=!1,H=!1,J=!1,$={offsetX:0,offsetY:0,scale:1},K=o({});return{run:function(e){return q||(r(),h(),P(),m(),S(),q=!0),v(e),this},reset:function(){O.resetScale(),m(),$.scale=1},pause:function(){J=!0,R.stop()},resume:function(){J=!1,R.restart()},rerender:function(){return l(),this},zoomOut:function(){return C(!0)},zoomIn:function(){return C(!1)},moveTo:function(e,n){O.graphCenterChanged($.offsetX-e*$.scale,$.offsetY-n*$.scale),l()},getGraphics:function(){return O},dispose:function(){D()},on:function(e,n){return K.on(e,n),this},off:function(e,n){return K.off(e,n),this}}}n.exports=r;var o=e("ngraph.events"),i=e("ngraph.forcelayout"),a=e("./svgGraphics.js"),u=e("../Utils/windowEvents.js"),s=e("../Input/domInputManager.js"),f=e("../Utils/timer.js"),c=e("../Utils/getDimensions.js"),d=e("../Input/dragndrop.js")},{"../Input/domInputManager.js":34,"../Input/dragndrop.js":35,"../Utils/getDimensions.js":42,"../Utils/timer.js":46,"../Utils/windowEvents.js":47,"./svgGraphics.js":49,"ngraph.events":6,"ngraph.forcelayout":7}],49:[function(e,n,t){function r(){function e(){var e=o("svg");return n=o("g").attr("buffered-rendering","dynamic"),e.appendChild(n),e}var n,t,r,u=0,s=0,f=1,c={},d={},l=function(e){return o("rect").attr("width",10).attr("height",10).attr("fill","#00a2e8")},p=function(e,n){e.attr("x",n.x-5).attr("y",n.y-5)},v=function(e){return o("line").attr("stroke","#999")},g=function(e,n,t){e.attr("x1",n.x).attr("y1",n.y).attr("x2",t.x).attr("y2",t.y)},h=function(e){e.fire("rescaled")},m={x:0,y:0},y={x:0,y:0},x={x:0,y:0},w=function(){if(n){var e="matrix("+f+", 0, 0,"+f+","+u+","+s+")";n.attr("transform",e)}};t=e();var b={getNodeUI:function(e){return c[e]},getLinkUI:function(e){return d[e]},node:function(e){return"function"==typeof e?(l=e,this):void 0},link:function(e){return"function"==typeof e?(v=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return g=e,this},beginRender:function(){},endRender:function(){},graphCenterChanged:function(e,n){u=e,s=n,w()},inputManager:a,translateRel:function(e,r){var o=t.createSVGPoint(),i=n.getCTM(),a=t.createSVGPoint().matrixTransform(i.inverse());o.x=e,o.y=r,o=o.matrixTransform(i.inverse()),o.x=(o.x-a.x)*i.a,o.y=(o.y-a.y)*i.d,i.e+=o.x,i.f+=o.y;var u="matrix("+i.a+", 0, 0,"+i.d+","+i.e+","+i.f+")";n.attr("transform",u)},scale:function(e,r){var o=t.createSVGPoint();o.x=r.x,o.y=r.y,o=o.matrixTransform(n.getCTM().inverse());var i=t.createSVGMatrix().translate(o.x,o.y).scale(e).translate(-o.x,-o.y),a=n.getCTM().multiply(i);f=a.a,u=a.e,s=a.f;var c="matrix("+a.a+", 0, 0,"+a.d+","+a.e+","+a.f+")";return n.attr("transform",c),h(this),f},resetScale:function(){f=1;var e="matrix(1, 0, 0, 1, 0, 0)";return n.attr("transform",e),h(this),this},init:function(e){e.appendChild(t),w(),"function"==typeof r&&r(t)},release:function(e){t&&e&&e.removeChild(t)},addLink:function(e,t){var r=v(e);if(r)return r.position=t,r.link=e,d[e.id]=r,n.childElementCount>0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):r=e),t},getSvgRoot:function(){return t}};return i(b),b}n.exports=r;var o=e("simplesvg"),i=e("ngraph.events"),a=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":34,"ngraph.events":6,simplesvg:27}],50:[function(e,n,t){function r(e){e=c(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,r,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=i(),P=a(),N=function(e){return u()},k=function(e){return s(3014898687)},A=function(){L.updateTransform(y),P.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),r&&r.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),P&&P.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){return"function"==typeof e?(N=e,this):void 0},link:function(e){return"function"==typeof e?(k=e,this):void 0},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:o,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&P.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,A()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=N(e);return r.id=t,r.position=n,r.node=e,P.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],A()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,A(),I(this),y[0]},resetScale:function(){return j(),r&&(_(),A()),this},init:function(o){var i={};if(e.preserveDrawingBuffer&&(i.preserveDrawingBuffer=!0),n=o,_(),j(),n.appendChild(t),r=t.getContext("experimental-webgl",i),!r){var a="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(a),a}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var u=e.clearColorValue;r.clearColor(u.r,u.g,u.b,u.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}L.load(r),L.updateSize(d/2,l/2),P.load(r),P.updateSize(d/2,l/2),A(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(m>t){if(0===m||m===t)return;var r=w[m];w[t]=r,r.id=t}},releaseNode:function(e){h>0&&(h-=1);var n=b[e.id];delete b[e.id],P.removeNode(n);var t=n.id;if(h>t){if(0===h||h===t)return;var r=x[h];x[t]=r,r.id=t,P.replaceProperties(n,r)}},renderNodes:function(){for(var e={x:0,y:0},n=0;h>n;++n){var t=x[n];e.x=t.position.x,e.y=t.position.y,p&&p(t,e),P.position(t,e)}},renderLinks:function(){if(!this.omitLinksRendering)for(var e={x:0,y:0},n={x:0,y:0},t=0;m>t;++t){var r=w[t],o=r.pos.from;n.x=o.x,n.y=-o.y,o=r.pos.to,e.x=o.x,e.y=-o.y,v&&v(r,n,e),L.position(r,n,e)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):g=e),t},setNodeProgram:function(e){if(!r&&e)P=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},setLinkProgram:function(e){if(!r&&e)L=e;else if(e)throw"Not implemented. Cannot swap shader on the fly... Yet."},transformClientToGraphCoordinates:function(e){return e.x=2*e.x/d-1,e.y=1-2*e.y/l,e.x=(e.x-y[12])/y[0],e.y=(e.y-y[13])/y[5],e.x=e.x*(d/2),e.y=e.y*(-l/2),e},transformGraphToClientCoordinates:function(e){return e.x=e.x/(d/2),e.y=e.y/(-l/2),e.x=e.x*y[0]+y[12],e.y=e.y*y[5]+y[13],e.x=(e.x+1)*d/2,e.y=(1-e.y)*l/2,e},getNodeAtClientPos:function(e,n){if("function"!=typeof n)return null;this.transformClientToGraphCoordinates(e);for(var t=0;h>t;++t)if(n(x[t],e.x,e.y))return x[t].node;return null}};return f(T),T}n.exports=r;var o=e("../Input/webglInputManager.js"),i=e("../WebGL/webglLinkProgram.js"),a=e("../WebGL/webglNodeProgram.js"),u=e("../WebGL/webglSquare.js"),s=e("../WebGL/webglLine.js"),f=e("ngraph.events"),c=e("ngraph.merge")},{"../Input/webglInputManager.js":36,"../WebGL/webglLine.js":58,"../WebGL/webglLinkProgram.js":59,"../WebGL/webglNodeProgram.js":60,"../WebGL/webglSquare.js":61,"ngraph.events":6,"ngraph.merge":24}],51:[function(e,n,t){function r(e){var n=10414335;if("string"==typeof e&&e)if(4===e.length&&(e=e.replace(/([^#])/g,"$1$1")),9===e.length)n=parseInt(e.substr(1),16);else{if(7!==e.length)throw'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: '+e;n=parseInt(e.substr(1),16)<<8|255}else"number"==typeof e&&(n=e);return n}n.exports=r},{}],52:[function(e,n,t){function r(e){this.canvas=window.document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.isDirty=!1,this.canvas.width=this.canvas.height=e}n.exports=r},{}],53:[function(e,n,t){function r(e){function n(n,t){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){var o=e.getShaderInfoLog(r);throw window.alert(o),o}return r}function t(t,r){var o=e.createProgram(),i=n(t,e.VERTEX_SHADER),a=n(r,e.FRAGMENT_SHADER);if(e.attachShader(o,i),e.attachShader(o,a),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){var u=e.getShaderInfoLog(o);throw window.alert(u),u}return o}function r(e,n,t){if((n+1)*t>e.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;oo;++o)e[n+o]=e[t+o]}function i(e,n,t,r){for(var o=0;r>o;++o){var i=e[n+o];e[n+o]=e[t+o],e[t+o]=i}}n.exports=r},{}],54:[function(e,n,t){function r(e){function n(){var e;for(E.isDirty=!1,e=0;e=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!o(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:r,getCoordinates:a,load:u};return E}function o(e){return 0===(e&e-1)}var i=e("./texture.js");n.exports=r},{"./texture.js":52}],55:[function(e,n,t){function r(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=r},{}],56:[function(e,n,t){function r(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*P,j*P,P))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*j)}var v,g,h,m,y,x,w,b,E,L,P=18,N=o(),k=i(),A=1024,j=0,_=new Float32Array(64);return{load:t,position:r,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function o(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function i(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var a=e("./webglAtlas.js"),u=e("./webgl.js");n.exports=r},{"./webgl.js":53,"./webglAtlas.js":54}],57:[function(e,n,t){function r(e){function n(){x=null}function t(e){x=e}function r(e){return"function"==typeof e&&k.push(e),j}function i(e){return"function"==typeof e&&N.push(e),j}function a(e){return"function"==typeof e&&P.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oo-i&&u?g(k,r):g(N,r),i=o,g(L,r)&&p(e))})}if(e.webglInputEvents)return e.webglInputEvents;var m,y,x=null,w=[],b=[],E=[],L=[],P=[],N=[],k=[],A=e.getGraphicsRoot();h(A);var j={mouseEnter:c,mouseLeave:f,mouseDown:s,mouseUp:u,mouseMove:a,click:i,dblClick:r,mouseCapture:t,releaseMouseCapture:n};return e.webglInputEvents=j,j}var o=e("../Utils/documentEvents.js");n.exports=r},{"../Utils/documentEvents.js":40}],58:[function(e,n,t){function r(e){return{color:o(e)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],59:[function(e,n,t){function r(){var e,n,t,r,i,a,u,s,f,c,d=6,l=2*(2*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT),p=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),v=["attribute vec2 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);"," color = a_color.abgr;","}"].join("\n"),g=0,h=new ArrayBuffer(16*l),m=new Float32Array(h),y=new Uint32Array(h),x=function(){if((g+1)*l>h.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,r=o(a),e=r.createProgram(v,p),n.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&r.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&r.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],60:[function(e,n,t){function r(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(N),P=n,N=t,L=e}}function n(e){d=e,v=o(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;P[t*x]=n.x,P[t*x+1]=-n.y,P[t*x+2]=e.size,N[t*x+3]=e.color}function r(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(N,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),P=new Float32Array(L),N=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:r,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],61:[function(e,n,t){function r(e,n){return{size:"number"==typeof e?e:10,color:o(n)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],62:[function(e,n,t){n.exports="0.8.1"},{}]},{},[1])(1)}); \ No newline at end of file +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,h=f*t+d*r+p,0!==v&&0!==h&&v>=0==h>=0?null:(y=s*d-f*c,0===y?null:(x=y<0?-y/2:y/2,x=0,w=c*p-d*l,b.x=(w<0?w-x:w+x)/y,w=f*l-s*p,b.y=(w<0?w-x:w+x)/y,b)))}n.exports=r},{}],4:[function(e,n,t){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":5,"./src/degree.js":6}],5:[function(e,n,t){function r(e,n){function t(e){h[e]/=2}function r(e){h[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;i0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function f(e,n,t){if(e<1||n<1||t<1)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=p();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;i0&&a.addLink(s,r-1+o*e+u),o>0&&a.addLink(s,r+(o-1)*e+u),i>0&&a.addLink(s,r+o*e+(i-1)*e*n)}return a}function c(e){if(e<0)throw new Error("Invalid number of nodes in balanced tree");var n,t=p(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;n= 0");var n,t=p();for(n=0;n=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,u=e("ngraph.random").random(o||42),s=p();for(i=0;i=0&&t.links.splice(n,1)),r&&(n=o(e,r.links),n>=0&&r.links.splice(n,1)),U(e,"remove"),F(),!0}function g(e,n){var t,r=f(e);if(!r)return null;for(t=0;t0&&(O.fire("changed",M),M.length=0)}function P(){return Object.keys?k:A}function k(e){if("function"==typeof e)for(var n=Object.keys(j),t=0;t=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return h.getBestNewPosition(e)},getBBox:function(){return h.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=r},{"./lib/bounds":16,"./lib/createBody":17,"./lib/dragForce":18,"./lib/eulerIntegrator":19,"./lib/spring":20,"./lib/springForce":21,"ngraph.expose":8,"ngraph.merge":13,"ngraph.quadtreebh":22}],16:[function(e,n,t){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;u1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=r},{}],20:[function(e,n,t){function r(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=r},{}],21:[function(e,n,t){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":8,"ngraph.merge":13,"ngraph.random":26}],22:[function(e,n,t){function r(e,n){return 0===n?e.quad0:1===n?e.quad1:2===n?e.quad2:3===n?e.quad3:null}function o(e,n,t){0===n?e.quad0=t:1===n?e.quad1=t:2===n?e.quad2=t:3===n&&(e.quad3=t)}n.exports=function(n){n=n||{},n.gravity="number"==typeof n.gravity?n.gravity:-1,n.theta="number"==typeof n.theta?n.theta:.8;var t=e("ngraph.random").random(1984),i=e("./node"),a=e("./insertStack"),u=e("./isSamePosition"),s=n.gravity,f=[],c=new a,d=n.theta,l=[],p=0,v=function(){var e=l[p];return e?(e.quad0=null,e.quad1=null,e.quad2=null,e.quad3=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0):(e=new i,l[p]=e),++p,e},h=v(),g=function(e){for(c.reset(),c.push(h,e);!c.isEmpty();){var n=c.pop(),i=n.node,a=n.body;if(i.body){var s=i.body;if(i.body=null,u(s.pos,a.pos)){var f=3;do{var d=t.nextDouble(),l=(i.right-i.left)*d,p=(i.bottom-i.top)*d;s.pos.x=i.left+l,s.pos.y=i.top+p,f-=1}while(f>0&&u(s.pos,a.pos));if(0===f&&u(s.pos,a.pos))return}c.push(i,s),c.push(i,a)}else{var g=a.pos.x,m=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*g,i.massY=i.massY+a.mass*m;var y=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;if(g>w){y+=1;var L=x;x=w,w+=w-L}if(m>E){y+=2;var N=b;b=E,E+=E-N}var P=r(i,y);P?c.push(P,a):(P=v(),P.left=x,P.top=b,P.right=w,P.bottom=E,P.body=a,o(i,y,P))}}},m=function(e){var n,r,o,i,a=f,u=0,c=0,l=1,p=0,v=1;for(a[0]=h;l;){var g=a[p],m=g.body;l-=1,p+=1;var y=m!==e;m&&y?(r=m.pos.x-e.pos.x,o=m.pos.y-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),n=s*m.mass*e.mass/(i*i*i),u+=n*r,c+=n*o):y&&(r=g.massX/g.mass-e.pos.x,o=g.massY/g.mass-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),(g.right-g.left)/io&&(o=u),si&&(i=s)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,p=0,h=v(),h.left=t,h.right=o,h.top=r,h.bottom=i,n=a-1,n>0&&(h.body=e[n]);n--;)g(e[n],h)};return{insertBodies:y,updateBodyForce:m,options:function(e){return e?("number"==typeof e.gravity&&(s=e.gravity),"number"==typeof e.theta&&(d=e.theta),this):{gravity:s,theta:d}}}}},{"./insertStack":23,"./isSamePosition":24,"./node":25,"ngraph.random":26}],23:[function(e,n,t){function r(){this.stack=[],this.popIdx=0}function o(e,n){this.node=e,this.body=n}n.exports=r,r.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new o(e,n),++this.popIdx},pop:function(){if(this.popIdx>0)return this.stack[--this.popIdx]},reset:function(){this.popIdx=0}}},{}],24:[function(e,n,t){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return t<1e-8&&r<1e-8}},{}],25:[function(e,n,t){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],26:[function(e,n,t){function r(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function o(e,n){var t=n||r();if("function"!=typeof t.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var r,o,i;for(r=e.length-1;r>0;--r)o=t.next(r+1),i=e[o],e[o]=e[r],e[r]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,r,o;for(n=e.length-1;n>0;--n)r=t.next(n+1),o=e[r],e[r]=e[n],e[n]=o;return e}}}n.exports={random:r,randomIterator:o}},{}],27:[function(e,n,t){function r(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=r},{}],28:[function(e,n,t){function r(e,n){var t=o(e);if(void 0===n)return t;for(var r=Object.keys(n),i=0;iv&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},A=function(e){p=!1,o.off("touchmove",k),o.off("touchend",A),o.off("touchcancel",A),c=null,r&&r(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,o.on("touchmove",k),o.on("touchend",A),o.on("touchcancel",A))},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=P(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_), +o.off("mousemove",w),o.off("mouseup",E),o.off("touchmove",k),o.off("touchend",A),o.off("touchcancel",A),N(null)}}}n.exports=r;var o=e("../Utils/documentEvents.js"),i=e("../Utils/browserInfo.js"),a=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":39,"../Utils/documentEvents.js":40,"../Utils/findElementPosition.js":41}],36:[function(e,n,t){function r(e,n){var t=o(n),r=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){r=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(r);var o=i[e.id];return o&&o.onStart&&o.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(r),r=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(r){var t=i[r.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=r;var o=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":57}],37:[function(e,n,t){function r(e,n){function t(e){return d[e]}n=o(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var r=i(n.seed),u=new a(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(e){return{x:r.next(n.maxX),y:r.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},h=function(e){for(var n=0;n=0:"boolean"!=typeof z||z}function r(){G=G||window.document.body,F=F||i(e,{springLength:80,springCoeff:2e-4}),O=O||a(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||s)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=f(function(){return p()},M)):(X=0,V=0,R=f(p,M)))}function h(){J||(W=!1,R.restart())}function g(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;e0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,h(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):r=e),t},getSvgRoot:function(){return t}};return i(b),b}n.exports=r;var o=e("simplesvg"),i=e("ngraph.events"),a=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":34,"ngraph.events":7,simplesvg:28}],50:[function(e,n,t){function r(e){e=c(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,r,d,l,p,v,h,g=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=i(),N=a(),P=function(e){return u()},k=function(e){return s(3014898687)},A=function(){L.updateTransform(y),N.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),r&&r.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),N&&N.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){if("function"==typeof e)return P=e,this},link:function(e){if("function"==typeof e)return k=e,this},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:o,beginRender:function(){},endRender:function(){m>0&&L.render(),g>0&&N.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,A()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=g++,r=P(e);return r.id=t,r.position=n,r.node=e,N.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],A()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,A(),I(this),y[0]},resetScale:function(){return j(),r&&(_(),A()),this},init:function(o){var i={};if(e.preserveDrawingBuffer&&(i.preserveDrawingBuffer=!0),n=o,_(),j(),n.appendChild(t),r=t.getContext("experimental-webgl",i),!r){var a="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(a),a}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var u=e.clearColorValue;r.clearColor(u.r,u.g,u.b,u.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}L.load(r),L.updateSize(d/2,l/2),N.load(r),N.updateSize(d/2,l/2),A(),"function"==typeof h&&h(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(t0&&(g-=1);var n=b[e.id];delete b[e.id],N.removeNode(n);var t=n.id;if(te.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;o=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*g,r.row*g,g,g),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/h<<0,i=r%h;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*g,i=n.row*g;r.drawImage(t,e.col*g,e.row*g,g,g,o,i,g,g),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,h=Math.sqrt(e||1024)<<0,g=h,m=1,y={},x=0,w=[],b=[];if(!o(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:r,getCoordinates:a,load:u};return E}function o(e){return 0===(e&e-1)}var i=e("./texture.js");n.exports=r},{"./texture.js":52}],55:[function(e,n,t){function r(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=r},{}],56:[function(e,n,t){function r(){function e(e,n){e.nativeObject&&g.deleteTexture(e.nativeObject);var t=g.createTexture();g.activeTexture(g["TEXTURE"+n]),g.bindTexture(g.TEXTURE_2D,t),g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,e.canvas),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MAG_FILTER,g.LINEAR),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MIN_FILTER,g.LINEAR_MIPMAP_NEAREST),g.generateMipmap(g.TEXTURE_2D),g.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*N,j*N,N))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){g.useProgram(h),g.bindBuffer(g.ARRAY_BUFFER,m),g.bufferData(g.ARRAY_BUFFER,_,g.DYNAMIC_DRAW),L&&(L=!1,g.uniformMatrix4fv(x.transform,!1,E),g.uniform2f(x.screenSize,w,b)),g.vertexAttribPointer(x.vertexPos,2,g.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),g.vertexAttribPointer(x.customAttributes,1,g.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),g.drawArrays(g.TRIANGLES,0,6*j)}var v,h,g,m,y,x,w,b,E,L,N=18,P=o(),k=i(),A=1024,j=0,_=new Float32Array(64);return{load:t,position:r,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function o(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function i(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var a=e("./webglAtlas.js"),u=e("./webgl.js");n.exports=r},{"./webgl.js":53,"./webglAtlas.js":54}],57:[function(e,n,t){function r(e){function n(){x=null}function t(e){x=e}function r(e){return"function"==typeof e&&k.push(e),j}function i(e){return"function"==typeof e&&P.push(e),j}function a(e){return"function"==typeof e&&N.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-og.byteLength){var e=new ArrayBuffer(2*g.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,g=e}};return{load:function(a){n=a,r=o(a),e=r.createProgram(v,p),n.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),h+=1,a=e.id},removeLink:function(e){h>0&&(h-=1),e.id0&&r.copyArrayPart(y,e.id*d,h*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,g,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*h),a=h-1},bringToFront:function(e){a>e.id&&r.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],60:[function(e,n,t){function r(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(P),N=n,P=t,L=e}}function n(e){d=e,v=o(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;N[t*x]=n.x,N[t*x+1]=-n.y,N[t*x+2]=e.size,P[t*x+3]=e.color}function r(e){y=!0,m=e}function i(e,n){h=e,g=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(P,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,h,g)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,h,g,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),N=new Float32Array(L),P=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:r,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],61:[function(e,n,t){function r(e,n){return{size:"number"==typeof e?e:10,color:o(n)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],62:[function(e,n,t){n.exports="0.8.1"},{}]},{},[1])(1)}); \ No newline at end of file From c4ef0520183435255a960c31ea31fedeb104d74f Mon Sep 17 00:00:00 2001 From: Andriy Kashcha Date: Mon, 24 Apr 2017 21:45:30 -0700 Subject: [PATCH 230/276] 0.8.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4cfe071..9b7ccd6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.8.2", + "version": "0.8.3", "description": "Graph Drawing Library", "main": "src/viva", "directories": { From a0c80779635ea423fef032423f4b2acb117675c8 Mon Sep 17 00:00:00 2001 From: josephrocca Date: Mon, 1 May 2017 17:18:45 +0800 Subject: [PATCH 231/276] A bit in the readme on live tuning? --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 5c97cf9..44f8de9 100644 --- a/README.md +++ b/README.md @@ -163,6 +163,8 @@ Now the result is much better: ![Grid 3x3](https://github.com/anvaka/VivaGraphJS/raw/master/packages/Images/gridGood.png) +You can tune values during simulation with `layout.simulation.springLength(newValue)`, `layout.simulation.springCoeff(newValue)`, etc. + Tuning layout algorithm is definitely one of the hardest part of using this library. It has to be improved in future to simplify usage. Each of the force directed algorithm parameters are described in the source code. From c69725bf512ce634d2aec54c821b951b7380a374 Mon Sep 17 00:00:00 2001 From: Alex Burner Date: Mon, 1 May 2017 13:37:28 -0700 Subject: [PATCH 232/276] Add direct link to ngraph repo in readme As a new user, I was confused about the `ngraph` family until I ran across the main repo page. It did not show up on the first page of results when I viewed the https://www.npmjs.com/search?q=ngraph link. I failed to understand that the core layout algorithms are decoupled from VivaGraphJS. This commit adds a link to the main repo in the readme and tries to specify that it contains the layout algorithms. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5c97cf9..5b6ac97 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ VivaGraph [![Build Status](https://travis-ci.org/anvaka/VivaGraphJS.svg)](https://travis-ci.org/anvaka/VivaGraphJS) ================================================== **VivaGraphJS** is designed to be extensible and to support different -rendering engines and layout algorithms. Underlying modules can be found via [ngraph](https://www.npmjs.com/search?q=ngraph) query. +rendering engines and layout algorithms. Underlying algorithms have been broken out into [ngraph](https://github.com/anvaka/ngraph). The larger family of modules can be found by [querying npm for "ngraph"](https://www.npmjs.com/search?q=ngraph). [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/anvaka/VivaGraphJS?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) From 7330a58329098be66df4222a474a5e41e85beb45 Mon Sep 17 00:00:00 2001 From: Alex Burner Date: Tue, 2 May 2017 18:53:21 -0700 Subject: [PATCH 233/276] Newline for npm query --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5b6ac97..6ad8c98 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ VivaGraph [![Build Status](https://travis-ci.org/anvaka/VivaGraphJS.svg)](https://travis-ci.org/anvaka/VivaGraphJS) ================================================== **VivaGraphJS** is designed to be extensible and to support different -rendering engines and layout algorithms. Underlying algorithms have been broken out into [ngraph](https://github.com/anvaka/ngraph). The larger family of modules can be found by [querying npm for "ngraph"](https://www.npmjs.com/search?q=ngraph). +rendering engines and layout algorithms. Underlying algorithms have been broken out into [ngraph](https://github.com/anvaka/ngraph). + +The larger family of modules can be found by [querying npm for "ngraph"](https://www.npmjs.com/search?q=ngraph). [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/anvaka/VivaGraphJS?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) From cc07eaa31be1f1f33f41839b9d4aadcf04e06412 Mon Sep 17 00:00:00 2001 From: josephrocca Date: Wed, 3 May 2017 15:25:16 +0800 Subject: [PATCH 234/276] Updated dynamic tuning details in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 44f8de9..bed591e 100644 --- a/README.md +++ b/README.md @@ -163,7 +163,7 @@ Now the result is much better: ![Grid 3x3](https://github.com/anvaka/VivaGraphJS/raw/master/packages/Images/gridGood.png) -You can tune values during simulation with `layout.simulation.springLength(newValue)`, `layout.simulation.springCoeff(newValue)`, etc. +You can tune values during simulation with `layout.simulator.springLength(newValue)`, `layout.simulator.springCoeff(newValue)`, etc. See all the values that you can tune in [this source file](https://github.com/anvaka/ngraph.physics.simulator/blob/master/index.js#L12). Tuning layout algorithm is definitely one of the hardest part of using this library. It has to be improved in future to simplify usage. Each of the force directed From 17d02727fa7cc46f127f5e7d21223a14d2a59521 Mon Sep 17 00:00:00 2001 From: Andriy Kashcha Date: Mon, 8 May 2017 22:35:41 -0700 Subject: [PATCH 235/276] Updated to latest ngraph.forcelayout --- dist/vivagraph.js | 628 ++++++++++++++++++++++++------------------ dist/vivagraph.min.js | 4 +- package.json | 3 +- 3 files changed, 358 insertions(+), 277 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 29c4caa..0a7e067 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -578,8 +578,11 @@ function augment(source, target, key) { module.exports = createLayout; module.exports.simulator = require('ngraph.physics.simulator'); +var eventify = require('ngraph.events'); + /** * Creates force based layout for a given graph. + * * @param {ngraph.graph} graph which needs to be laid out * @param {object} physicsSettings if you need custom settings * for physics simulator you can pass your own settings here. If it's not passed @@ -593,21 +596,46 @@ function createLayout(graph, physicsSettings) { var createSimulator = require('ngraph.physics.simulator'); var physicsSimulator = createSimulator(physicsSettings); - var nodeBodies = typeof Object.create === 'function' ? Object.create(null) : {}; + var nodeBodies = Object.create(null); var springs = {}; + var bodiesCount = 0; var springTransform = physicsSimulator.settings.springTransform || noop; - // Initialize physical objects according to what we have in the graph: + // Initialize physics with what we have in the graph: initPhysics(); - listenToGraphEvents(); + listenToEvents(); + + var wasStable = false; var api = { /** * Performs one step of iterative layout algorithm + * + * @returns {boolean} true if the system should be considered stable; Flase otherwise. + * The system is stable if no further call to `step()` can improve the layout. */ step: function() { - return physicsSimulator.step(); + if (bodiesCount === 0) return true; // TODO: This will never fire 'stable' + + var lastMove = physicsSimulator.step(); + + // Save the movement in case if someone wants to query it in the step + // callback. + api.lastMove = lastMove; + + // Allow listeners to perform low-level actions after nodes are updated. + api.fire('step'); + + var ratio = lastMove/bodiesCount; + var isStableNow = ratio <= 0.01; // TODO: The number is somewhat arbitrary... + + if (wasStable !== isStableNow) { + wasStable = isStableNow; + onStableChanged(isStableNow); + } + + return isStableNow; }, /** @@ -653,6 +681,11 @@ function createLayout(graph, physicsSettings) { return physicsSimulator.getBBox(); }, + /** + * Iterates over each body in the layout simulator and performs a callback(body, nodeId) + */ + forEachBody: forEachBody, + /* * Requests layout algorithm to pin/unpin node to its current position * Pinned nodes should not be affected by layout algorithm and always @@ -675,6 +708,7 @@ function createLayout(graph, physicsSettings) { */ dispose: function() { graph.off('changed', onGraphChanged); + api.fire('disposed'); }, /** @@ -696,15 +730,33 @@ function createLayout(graph, physicsSettings) { /** * [Read only] Gets current physics simulator */ - simulator: physicsSimulator + simulator: physicsSimulator, + + /** + * Gets the graph that was used for layout + */ + graph: graph, + + /** + * Gets amount of movement performed during last step opeartion + */ + lastMove: 0 }; + eventify(api); + return api; + function forEachBody(cb) { + Object.keys(nodeBodies).forEach(function(bodyId) { + cb(nodeBodies[bodyId], bodyId); + }); + } + function getSpring(fromId, toId) { var linkId; if (toId === undefined) { - if (typeof fromId === 'string') { + if (typeof fromId !== 'object') { // assume fromId as a linkId: linkId = fromId; } else { @@ -725,10 +777,14 @@ function createLayout(graph, physicsSettings) { return nodeBodies[nodeId]; } - function listenToGraphEvents() { + function listenToEvents() { graph.on('changed', onGraphChanged); } + function onStableChanged(isStable) { + api.fire('stable', isStable); + } + function onGraphChanged(changes) { for (var i = 0; i < changes.length; ++i) { var change = changes[i]; @@ -748,12 +804,17 @@ function createLayout(graph, physicsSettings) { } } } + bodiesCount = graph.getNodesCount(); } function initPhysics() { + bodiesCount = 0; + graph.forEachNode(function (node) { initBody(node.id); + bodiesCount += 1; }); + graph.forEachLink(initLink); } @@ -772,6 +833,7 @@ function createLayout(graph, physicsSettings) { } body = physicsSimulator.addBodyAt(pos); + body.id = nodeId; nodeBodies[nodeId] = body; updateBodyMass(nodeId); @@ -872,13 +934,15 @@ function createLayout(graph, physicsSettings) { * @returns {Number} recommended mass of the body; */ function nodeMass(nodeId) { - return 1 + graph.getLinks(nodeId).length / 3.0; + var links = graph.getLinks(nodeId); + if (!links) return 1; + return 1 + links.length / 3.0; } } function noop() { } -},{"ngraph.physics.simulator":15}],10:[function(require,module,exports){ +},{"ngraph.events":7,"ngraph.physics.simulator":15}],10:[function(require,module,exports){ module.exports = load; var createGraph = require('ngraph.graph'); @@ -1888,6 +1952,7 @@ function physicsSimulator(settings) { var Spring = require('./lib/spring'); var expose = require('ngraph.expose'); var merge = require('ngraph.merge'); + var eventify = require('ngraph.events'); settings = merge(settings, { /** @@ -1924,11 +1989,6 @@ function physicsSimulator(settings) { * Default time step (dt) for forces integration */ timeStep : 20, - - /** - * Maximum movement of the system which can be considered as stabilized - */ - stableThreshold: 0.009 }); // We allow clients to override basic factory methods: @@ -1946,6 +2006,8 @@ function physicsSimulator(settings) { springForce = createSpringForce(settings), dragForce = createDragForce(settings); + var totalMovement = 0; // how much movement we made on last step + var publicApi = { /** * Array of bodies, registered with current simulator @@ -1955,6 +2017,8 @@ function physicsSimulator(settings) { */ bodies: bodies, + quadTree: quadTree, + /** * Array of springs, registered with current simulator * @@ -1975,11 +2039,11 @@ function physicsSimulator(settings) { */ step: function () { accumulateForces(); - var totalMovement = integrate(bodies, settings.timeStep); + var movement = integrate(bodies, settings.timeStep); bounds.update(); - return totalMovement < settings.stableThreshold; + return movement; }, /** @@ -2057,6 +2121,13 @@ function physicsSimulator(settings) { return spring; }, + /** + * Returns amount of movement performed on last step() call + */ + getTotalMovement: function () { + return totalMovement; + }, + /** * Removes spring from the system * @@ -2108,6 +2179,8 @@ function physicsSimulator(settings) { // allow settings modification via public API: expose(settings, publicApi); + eventify(publicApi); + return publicApi; function accumulateForces() { @@ -2138,7 +2211,7 @@ function physicsSimulator(settings) { } }; -},{"./lib/bounds":16,"./lib/createBody":17,"./lib/dragForce":18,"./lib/eulerIntegrator":19,"./lib/spring":20,"./lib/springForce":21,"ngraph.expose":8,"ngraph.merge":13,"ngraph.quadtreebh":22}],16:[function(require,module,exports){ +},{"./lib/bounds":16,"./lib/createBody":17,"./lib/dragForce":18,"./lib/eulerIntegrator":19,"./lib/spring":20,"./lib/springForce":21,"ngraph.events":7,"ngraph.expose":8,"ngraph.merge":13,"ngraph.quadtreebh":22}],16:[function(require,module,exports){ module.exports = function (bodies, settings) { var random = require('ngraph.random').random(42); var boundingBox = { x1: 0, y1: 0, x2: 0, y2: 0 }; @@ -2272,6 +2345,10 @@ function integrate(bodies, timeStep) { i, max = bodies.length; + if (max === 0) { + return 0; + } + for (i = 0; i < max; ++i) { var body = bodies[i], coeff = timeStep / body.mass; @@ -2296,7 +2373,7 @@ function integrate(bodies, timeStep) { tx += Math.abs(dx); ty += Math.abs(dy); } - return (tx * tx + ty * ty)/bodies.length; + return (tx * tx + ty * ty)/max; } },{}],20:[function(require,module,exports){ @@ -2393,289 +2470,292 @@ module.exports = function(options) { nodesCache = [], currentInCache = 0, - newNode = function() { - // To avoid pressure on GC we reuse nodes. - var node = nodesCache[currentInCache]; - if (node) { - node.quad0 = null; - node.quad1 = null; - node.quad2 = null; - node.quad3 = null; - node.body = null; - node.mass = node.massX = node.massY = 0; - node.left = node.right = node.top = node.bottom = 0; - } else { - node = new Node(); - nodesCache[currentInCache] = node; - } + root = newNode(); - ++currentInCache; - return node; + return { + insertBodies: insertBodies, + /** + * Gets root node if its present + */ + getRoot: function() { + return root; }, - - root = newNode(), - - // Inserts body to the tree - insert = function(newBody) { - insertStack.reset(); - insertStack.push(root, newBody); - - while (!insertStack.isEmpty()) { - var stackItem = insertStack.pop(), - node = stackItem.node, - body = stackItem.body; - - if (!node.body) { - // This is internal node. Update the total mass of the node and center-of-mass. - var x = body.pos.x; - var y = body.pos.y; - node.mass = node.mass + body.mass; - node.massX = node.massX + body.mass * x; - node.massY = node.massY + body.mass * y; - - // Recursively insert the body in the appropriate quadrant. - // But first find the appropriate quadrant. - var quadIdx = 0, // Assume we are in the 0's quad. - left = node.left, - right = (node.right + left) / 2, - top = node.top, - bottom = (node.bottom + top) / 2; - - if (x > right) { // somewhere in the eastern part. - quadIdx = quadIdx + 1; - var oldLeft = left; - left = right; - right = right + (right - oldLeft); - } - if (y > bottom) { // and in south. - quadIdx = quadIdx + 2; - var oldTop = top; - top = bottom; - bottom = bottom + (bottom - oldTop); - } - - var child = getChild(node, quadIdx); - if (!child) { - // The node is internal but this quadrant is not taken. Add - // subnode to it. - child = newNode(); - child.left = left; - child.top = top; - child.right = right; - child.bottom = bottom; - child.body = body; - - setChild(node, quadIdx, child); - } else { - // continue searching in this quadrant. - insertStack.push(child, body); - } - } else { - // We are trying to add to the leaf node. - // We have to convert current leaf into internal node - // and continue adding two nodes. - var oldBody = node.body; - node.body = null; // internal nodes do not cary bodies - - if (isSamePosition(oldBody.pos, body.pos)) { - // Prevent infinite subdivision by bumping one node - // anywhere in this quadrant - var retriesCount = 3; - do { - var offset = random.nextDouble(); - var dx = (node.right - node.left) * offset; - var dy = (node.bottom - node.top) * offset; - - oldBody.pos.x = node.left + dx; - oldBody.pos.y = node.top + dy; - retriesCount -= 1; - // Make sure we don't bump it out of the box. If we do, next iteration should fix it - } while (retriesCount > 0 && isSamePosition(oldBody.pos, body.pos)); - - if (retriesCount === 0 && isSamePosition(oldBody.pos, body.pos)) { - // This is very bad, we ran out of precision. - // if we do not return from the method we'll get into - // infinite loop here. So we sacrifice correctness of layout, and keep the app running - // Next layout iteration should get larger bounding box in the first step and fix this - return; - } - } - // Next iteration should subdivide node further. - insertStack.push(node, oldBody); - insertStack.push(node, body); + updateBodyForce: update, + options: function(newOptions) { + if (newOptions) { + if (typeof newOptions.gravity === 'number') { + gravity = newOptions.gravity; } + if (typeof newOptions.theta === 'number') { + theta = newOptions.theta; + } + + return this; } - }, - update = function(sourceBody) { - var queue = updateQueue, - v, - dx, - dy, - r, fx = 0, - fy = 0, - queueLength = 1, - shiftIdx = 0, - pushIdx = 1; - - queue[0] = root; - - while (queueLength) { - var node = queue[shiftIdx], - body = node.body; - - queueLength -= 1; - shiftIdx += 1; - var differentBody = (body !== sourceBody); - if (body && differentBody) { - // If the current node is a leaf node (and it is not source body), - // calculate the force exerted by the current node on body, and add this - // amount to body's net force. - dx = body.pos.x - sourceBody.pos.x; - dy = body.pos.y - sourceBody.pos.y; - r = Math.sqrt(dx * dx + dy * dy); + return { + gravity: gravity, + theta: theta + }; + } + }; - if (r === 0) { - // Poor man's protection against zero distance. - dx = (random.nextDouble() - 0.5) / 50; - dy = (random.nextDouble() - 0.5) / 50; - r = Math.sqrt(dx * dx + dy * dy); - } + function newNode() { + // To avoid pressure on GC we reuse nodes. + var node = nodesCache[currentInCache]; + if (node) { + node.quad0 = null; + node.quad1 = null; + node.quad2 = null; + node.quad3 = null; + node.body = null; + node.mass = node.massX = node.massY = 0; + node.left = node.right = node.top = node.bottom = 0; + } else { + node = new Node(); + nodesCache[currentInCache] = node; + } + + ++currentInCache; + return node; + } + + function update(sourceBody) { + var queue = updateQueue, + v, + dx, + dy, + r, fx = 0, + fy = 0, + queueLength = 1, + shiftIdx = 0, + pushIdx = 1; + + queue[0] = root; + + while (queueLength) { + var node = queue[shiftIdx], + body = node.body; + + queueLength -= 1; + shiftIdx += 1; + var differentBody = (body !== sourceBody); + if (body && differentBody) { + // If the current node is a leaf node (and it is not source body), + // calculate the force exerted by the current node on body, and add this + // amount to body's net force. + dx = body.pos.x - sourceBody.pos.x; + dy = body.pos.y - sourceBody.pos.y; + r = Math.sqrt(dx * dx + dy * dy); + + if (r === 0) { + // Poor man's protection against zero distance. + dx = (random.nextDouble() - 0.5) / 50; + dy = (random.nextDouble() - 0.5) / 50; + r = Math.sqrt(dx * dx + dy * dy); + } - // This is standard gravition force calculation but we divide - // by r^3 to save two operations when normalizing force vector. - v = gravity * body.mass * sourceBody.mass / (r * r * r); + // This is standard gravition force calculation but we divide + // by r^3 to save two operations when normalizing force vector. + v = gravity * body.mass * sourceBody.mass / (r * r * r); + fx += v * dx; + fy += v * dy; + } else if (differentBody) { + // Otherwise, calculate the ratio s / r, where s is the width of the region + // represented by the internal node, and r is the distance between the body + // and the node's center-of-mass + dx = node.massX / node.mass - sourceBody.pos.x; + dy = node.massY / node.mass - sourceBody.pos.y; + r = Math.sqrt(dx * dx + dy * dy); + + if (r === 0) { + // Sorry about code duplucation. I don't want to create many functions + // right away. Just want to see performance first. + dx = (random.nextDouble() - 0.5) / 50; + dy = (random.nextDouble() - 0.5) / 50; + r = Math.sqrt(dx * dx + dy * dy); + } + // If s / r < θ, treat this internal node as a single body, and calculate the + // force it exerts on sourceBody, and add this amount to sourceBody's net force. + if ((node.right - node.left) / r < theta) { + // in the if statement above we consider node's width only + // because the region was squarified during tree creation. + // Thus there is no difference between using width or height. + v = gravity * node.mass * sourceBody.mass / (r * r * r); fx += v * dx; fy += v * dy; - } else if (differentBody) { - // Otherwise, calculate the ratio s / r, where s is the width of the region - // represented by the internal node, and r is the distance between the body - // and the node's center-of-mass - dx = node.massX / node.mass - sourceBody.pos.x; - dy = node.massY / node.mass - sourceBody.pos.y; - r = Math.sqrt(dx * dx + dy * dy); + } else { + // Otherwise, run the procedure recursively on each of the current node's children. - if (r === 0) { - // Sorry about code duplucation. I don't want to create many functions - // right away. Just want to see performance first. - dx = (random.nextDouble() - 0.5) / 50; - dy = (random.nextDouble() - 0.5) / 50; - r = Math.sqrt(dx * dx + dy * dy); + // I intentionally unfolded this loop, to save several CPU cycles. + if (node.quad0) { + queue[pushIdx] = node.quad0; + queueLength += 1; + pushIdx += 1; } - // If s / r < θ, treat this internal node as a single body, and calculate the - // force it exerts on sourceBody, and add this amount to sourceBody's net force. - if ((node.right - node.left) / r < theta) { - // in the if statement above we consider node's width only - // because the region was squarified during tree creation. - // Thus there is no difference between using width or height. - v = gravity * node.mass * sourceBody.mass / (r * r * r); - fx += v * dx; - fy += v * dy; - } else { - // Otherwise, run the procedure recursively on each of the current node's children. - - // I intentionally unfolded this loop, to save several CPU cycles. - if (node.quad0) { - queue[pushIdx] = node.quad0; - queueLength += 1; - pushIdx += 1; - } - if (node.quad1) { - queue[pushIdx] = node.quad1; - queueLength += 1; - pushIdx += 1; - } - if (node.quad2) { - queue[pushIdx] = node.quad2; - queueLength += 1; - pushIdx += 1; - } - if (node.quad3) { - queue[pushIdx] = node.quad3; - queueLength += 1; - pushIdx += 1; - } + if (node.quad1) { + queue[pushIdx] = node.quad1; + queueLength += 1; + pushIdx += 1; + } + if (node.quad2) { + queue[pushIdx] = node.quad2; + queueLength += 1; + pushIdx += 1; + } + if (node.quad3) { + queue[pushIdx] = node.quad3; + queueLength += 1; + pushIdx += 1; } } } + } - sourceBody.force.x += fx; - sourceBody.force.y += fy; - }, + sourceBody.force.x += fx; + sourceBody.force.y += fy; + } - insertBodies = function(bodies) { - var x1 = Number.MAX_VALUE, - y1 = Number.MAX_VALUE, - x2 = Number.MIN_VALUE, - y2 = Number.MIN_VALUE, - i, - max = bodies.length; + function insertBodies(bodies) { + var x1 = Number.MAX_VALUE, + y1 = Number.MAX_VALUE, + x2 = Number.MIN_VALUE, + y2 = Number.MIN_VALUE, + i, + max = bodies.length; - // To reduce quad tree depth we are looking for exact bounding box of all particles. - i = max; - while (i--) { - var x = bodies[i].pos.x; - var y = bodies[i].pos.y; - if (x < x1) { - x1 = x; - } - if (x > x2) { - x2 = x; - } - if (y < y1) { - y1 = y; - } - if (y > y2) { - y2 = y; - } + // To reduce quad tree depth we are looking for exact bounding box of all particles. + i = max; + while (i--) { + var x = bodies[i].pos.x; + var y = bodies[i].pos.y; + if (x < x1) { + x1 = x; } - - // Squarify the bounds. - var dx = x2 - x1, - dy = y2 - y1; - if (dx > dy) { - y2 = y1 + dx; - } else { - x2 = x1 + dy; + if (x > x2) { + x2 = x; } - - currentInCache = 0; - root = newNode(); - root.left = x1; - root.right = x2; - root.top = y1; - root.bottom = y2; - - i = max - 1; - if (i > 0) { - root.body = bodies[i]; + if (y < y1) { + y1 = y; } - while (i--) { - insert(bodies[i], root); + if (y > y2) { + y2 = y; } - }; + } - return { - insertBodies: insertBodies, - updateBodyForce: update, - options: function(newOptions) { - if (newOptions) { - if (typeof newOptions.gravity === 'number') { - gravity = newOptions.gravity; + // Squarify the bounds. + var dx = x2 - x1, + dy = y2 - y1; + if (dx > dy) { + y2 = y1 + dx; + } else { + x2 = x1 + dy; + } + + currentInCache = 0; + root = newNode(); + root.left = x1; + root.right = x2; + root.top = y1; + root.bottom = y2; + + i = max - 1; + if (i >= 0) { + root.body = bodies[i]; + } + while (i--) { + insert(bodies[i], root); + } + } + + function insert(newBody) { + insertStack.reset(); + insertStack.push(root, newBody); + + while (!insertStack.isEmpty()) { + var stackItem = insertStack.pop(), + node = stackItem.node, + body = stackItem.body; + + if (!node.body) { + // This is internal node. Update the total mass of the node and center-of-mass. + var x = body.pos.x; + var y = body.pos.y; + node.mass = node.mass + body.mass; + node.massX = node.massX + body.mass * x; + node.massY = node.massY + body.mass * y; + + // Recursively insert the body in the appropriate quadrant. + // But first find the appropriate quadrant. + var quadIdx = 0, // Assume we are in the 0's quad. + left = node.left, + right = (node.right + left) / 2, + top = node.top, + bottom = (node.bottom + top) / 2; + + if (x > right) { // somewhere in the eastern part. + quadIdx = quadIdx + 1; + left = right; + right = node.right; } - if (typeof newOptions.theta === 'number') { - theta = newOptions.theta; + if (y > bottom) { // and in south. + quadIdx = quadIdx + 2; + top = bottom; + bottom = node.bottom; } - return this; + var child = getChild(node, quadIdx); + if (!child) { + // The node is internal but this quadrant is not taken. Add + // subnode to it. + child = newNode(); + child.left = left; + child.top = top; + child.right = right; + child.bottom = bottom; + child.body = body; + + setChild(node, quadIdx, child); + } else { + // continue searching in this quadrant. + insertStack.push(child, body); + } + } else { + // We are trying to add to the leaf node. + // We have to convert current leaf into internal node + // and continue adding two nodes. + var oldBody = node.body; + node.body = null; // internal nodes do not cary bodies + + if (isSamePosition(oldBody.pos, body.pos)) { + // Prevent infinite subdivision by bumping one node + // anywhere in this quadrant + var retriesCount = 3; + do { + var offset = random.nextDouble(); + var dx = (node.right - node.left) * offset; + var dy = (node.bottom - node.top) * offset; + + oldBody.pos.x = node.left + dx; + oldBody.pos.y = node.top + dy; + retriesCount -= 1; + // Make sure we don't bump it out of the box. If we do, next iteration should fix it + } while (retriesCount > 0 && isSamePosition(oldBody.pos, body.pos)); + + if (retriesCount === 0 && isSamePosition(oldBody.pos, body.pos)) { + // This is very bad, we ran out of precision. + // if we do not return from the method we'll get into + // infinite loop here. So we sacrifice correctness of layout, and keep the app running + // Next layout iteration should get larger bounding box in the first step and fix this + return; + } + } + // Next iteration should subdivide node further. + insertStack.push(node, oldBody); + insertStack.push(node, body); } - - return { - gravity: gravity, - theta: theta - }; } - }; + } }; function getChild(node, idx) { diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index b926426..c84b0b7 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,h=f*t+d*r+p,0!==v&&0!==h&&v>=0==h>=0?null:(y=s*d-f*c,0===y?null:(x=y<0?-y/2:y/2,x=0,w=c*p-d*l,b.x=(w<0?w-x:w+x)/y,w=f*l-s*p,b.y=(w<0?w-x:w+x)/y,b)))}n.exports=r},{}],4:[function(e,n,t){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":5,"./src/degree.js":6}],5:[function(e,n,t){function r(e,n){function t(e){h[e]/=2}function r(e){h[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;i0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function f(e,n,t){if(e<1||n<1||t<1)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=p();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;i0&&a.addLink(s,r-1+o*e+u),o>0&&a.addLink(s,r+(o-1)*e+u),i>0&&a.addLink(s,r+o*e+(i-1)*e*n)}return a}function c(e){if(e<0)throw new Error("Invalid number of nodes in balanced tree");var n,t=p(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;n= 0");var n,t=p();for(n=0;n=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,u=e("ngraph.random").random(o||42),s=p();for(i=0;i=0&&t.links.splice(n,1)),r&&(n=o(e,r.links),n>=0&&r.links.splice(n,1)),U(e,"remove"),F(),!0}function g(e,n){var t,r=f(e);if(!r)return null;for(t=0;t0&&(O.fire("changed",M),M.length=0)}function P(){return Object.keys?k:A}function k(e){if("function"==typeof e)for(var n=Object.keys(j),t=0;t=0?i:-1,o);return p.push(a),a},removeSpring:function(e){if(e){var n=p.indexOf(e);return n>-1?(p.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return h.getBestNewPosition(e)},getBBox:function(){return h.box},gravity:function(e){return void 0!==e?(n.gravity=e,v.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,v.options({theta:e}),this):n.theta}};return o(n,y),y}n.exports=r},{"./lib/bounds":16,"./lib/createBody":17,"./lib/dragForce":18,"./lib/eulerIntegrator":19,"./lib/spring":20,"./lib/springForce":21,"ngraph.expose":8,"ngraph.merge":13,"ngraph.quadtreebh":22}],16:[function(e,n,t){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;u1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/e.length}n.exports=r},{}],20:[function(e,n,t){function r(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=r},{}],21:[function(e,n,t){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":8,"ngraph.merge":13,"ngraph.random":26}],22:[function(e,n,t){function r(e,n){return 0===n?e.quad0:1===n?e.quad1:2===n?e.quad2:3===n?e.quad3:null}function o(e,n,t){0===n?e.quad0=t:1===n?e.quad1=t:2===n?e.quad2=t:3===n&&(e.quad3=t)}n.exports=function(n){n=n||{},n.gravity="number"==typeof n.gravity?n.gravity:-1,n.theta="number"==typeof n.theta?n.theta:.8;var t=e("ngraph.random").random(1984),i=e("./node"),a=e("./insertStack"),u=e("./isSamePosition"),s=n.gravity,f=[],c=new a,d=n.theta,l=[],p=0,v=function(){var e=l[p];return e?(e.quad0=null,e.quad1=null,e.quad2=null,e.quad3=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0):(e=new i,l[p]=e),++p,e},h=v(),g=function(e){for(c.reset(),c.push(h,e);!c.isEmpty();){var n=c.pop(),i=n.node,a=n.body;if(i.body){var s=i.body;if(i.body=null,u(s.pos,a.pos)){var f=3;do{var d=t.nextDouble(),l=(i.right-i.left)*d,p=(i.bottom-i.top)*d;s.pos.x=i.left+l,s.pos.y=i.top+p,f-=1}while(f>0&&u(s.pos,a.pos));if(0===f&&u(s.pos,a.pos))return}c.push(i,s),c.push(i,a)}else{var g=a.pos.x,m=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*g,i.massY=i.massY+a.mass*m;var y=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;if(g>w){y+=1;var L=x;x=w,w+=w-L}if(m>E){y+=2;var N=b;b=E,E+=E-N}var P=r(i,y);P?c.push(P,a):(P=v(),P.left=x,P.top=b,P.right=w,P.bottom=E,P.body=a,o(i,y,P))}}},m=function(e){var n,r,o,i,a=f,u=0,c=0,l=1,p=0,v=1;for(a[0]=h;l;){var g=a[p],m=g.body;l-=1,p+=1;var y=m!==e;m&&y?(r=m.pos.x-e.pos.x,o=m.pos.y-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),n=s*m.mass*e.mass/(i*i*i),u+=n*r,c+=n*o):y&&(r=g.massX/g.mass-e.pos.x,o=g.massY/g.mass-e.pos.y,i=Math.sqrt(r*r+o*o),0===i&&(r=(t.nextDouble()-.5)/50,o=(t.nextDouble()-.5)/50,i=Math.sqrt(r*r+o*o)),(g.right-g.left)/io&&(o=u),si&&(i=s)}var f=o-t,c=i-r;for(f>c?i=r+f:o=t+c,p=0,h=v(),h.left=t,h.right=o,h.top=r,h.bottom=i,n=a-1,n>0&&(h.body=e[n]);n--;)g(e[n],h)};return{insertBodies:y,updateBodyForce:m,options:function(e){return e?("number"==typeof e.gravity&&(s=e.gravity),"number"==typeof e.theta&&(d=e.theta),this):{gravity:s,theta:d}}}}},{"./insertStack":23,"./isSamePosition":24,"./node":25,"ngraph.random":26}],23:[function(e,n,t){function r(){this.stack=[],this.popIdx=0}function o(e,n){this.node=e,this.body=n}n.exports=r,r.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new o(e,n),++this.popIdx},pop:function(){if(this.popIdx>0)return this.stack[--this.popIdx]},reset:function(){this.popIdx=0}}},{}],24:[function(e,n,t){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return t<1e-8&&r<1e-8}},{}],25:[function(e,n,t){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],26:[function(e,n,t){function r(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function o(e,n){var t=n||r();if("function"!=typeof t.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var r,o,i;for(r=e.length-1;r>0;--r)o=t.next(r+1),i=e[o],e[o]=e[r],e[r]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,r,o;for(n=e.length-1;n>0;--n)r=t.next(n+1),o=e[r],e[r]=e[n],e[n]=o;return e}}}n.exports={random:r,randomIterator:o}},{}],27:[function(e,n,t){function r(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=r},{}],28:[function(e,n,t){function r(e,n){var t=o(e);if(void 0===n)return t;for(var r=Object.keys(n),i=0;iv&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},A=function(e){p=!1,o.off("touchmove",k),o.off("touchend",A),o.off("touchcancel",A),c=null,r&&r(e)},j=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,o.on("touchmove",k),o.on("touchend",A),o.on("touchcancel",A))},_=function(e){return 1===e.touches.length?j(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=P(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_), -o.off("mousemove",w),o.off("mouseup",E),o.off("touchmove",k),o.off("touchend",A),o.off("touchcancel",A),N(null)}}}n.exports=r;var o=e("../Utils/documentEvents.js"),i=e("../Utils/browserInfo.js"),a=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":39,"../Utils/documentEvents.js":40,"../Utils/findElementPosition.js":41}],36:[function(e,n,t){function r(e,n){var t=o(n),r=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){r=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(r);var o=i[e.id];return o&&o.onStart&&o.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(r),r=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(r){var t=i[r.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=r;var o=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":57}],37:[function(e,n,t){function r(e,n){function t(e){return d[e]}n=o(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var r=i(n.seed),u=new a(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(e){return{x:r.next(n.maxX),y:r.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},h=function(e){for(var n=0;n=0:"boolean"!=typeof z||z}function r(){G=G||window.document.body,F=F||i(e,{springLength:80,springCoeff:2e-4}),O=O||a(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||s)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=f(function(){return p()},M)):(X=0,V=0,R=f(p,M)))}function h(){J||(W=!1,R.restart())}function g(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;e0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,h(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):r=e),t},getSvgRoot:function(){return t}};return i(b),b}n.exports=r;var o=e("simplesvg"),i=e("ngraph.events"),a=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":34,"ngraph.events":7,simplesvg:28}],50:[function(e,n,t){function r(e){e=c(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,r,d,l,p,v,h,g=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=i(),N=a(),P=function(e){return u()},k=function(e){return s(3014898687)},A=function(){L.updateTransform(y),N.updateTransform(y)},j=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),r&&r.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),N&&N.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){if("function"==typeof e)return P=e,this},link:function(e){if("function"==typeof e)return k=e,this},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:o,beginRender:function(){},endRender:function(){m>0&&L.render(),g>0&&N.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,A()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=g++,r=P(e);return r.id=t,r.position=n,r.node=e,N.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],A()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,A(),I(this),y[0]},resetScale:function(){return j(),r&&(_(),A()),this},init:function(o){var i={};if(e.preserveDrawingBuffer&&(i.preserveDrawingBuffer=!0),n=o,_(),j(),n.appendChild(t),r=t.getContext("experimental-webgl",i),!r){var a="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(a),a}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var u=e.clearColorValue;r.clearColor(u.r,u.g,u.b,u.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}L.load(r),L.updateSize(d/2,l/2),N.load(r),N.updateSize(d/2,l/2),A(),"function"==typeof h&&h(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(t0&&(g-=1);var n=b[e.id];delete b[e.id],N.removeNode(n);var t=n.id;if(te.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;o=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*g,r.row*g,g,g),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/h<<0,i=r%h;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*g,i=n.row*g;r.drawImage(t,e.col*g,e.row*g,g,g,o,i,g,g),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,h=Math.sqrt(e||1024)<<0,g=h,m=1,y={},x=0,w=[],b=[];if(!o(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:r,getCoordinates:a,load:u};return E}function o(e){return 0===(e&e-1)}var i=e("./texture.js");n.exports=r},{"./texture.js":52}],55:[function(e,n,t){function r(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=r},{}],56:[function(e,n,t){function r(){function e(e,n){e.nativeObject&&g.deleteTexture(e.nativeObject);var t=g.createTexture();g.activeTexture(g["TEXTURE"+n]),g.bindTexture(g.TEXTURE_2D,t),g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,e.canvas),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MAG_FILTER,g.LINEAR),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MIN_FILTER,g.LINEAR_MIPMAP_NEAREST),g.generateMipmap(g.TEXTURE_2D),g.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(j-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*N,j*N,N))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){g.useProgram(h),g.bindBuffer(g.ARRAY_BUFFER,m),g.bufferData(g.ARRAY_BUFFER,_,g.DYNAMIC_DRAW),L&&(L=!1,g.uniformMatrix4fv(x.transform,!1,E),g.uniform2f(x.screenSize,w,b)),g.vertexAttribPointer(x.vertexPos,2,g.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),g.vertexAttribPointer(x.customAttributes,1,g.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),g.drawArrays(g.TRIANGLES,0,6*j)}var v,h,g,m,y,x,w,b,E,L,N=18,P=o(),k=i(),A=1024,j=0,_=new Float32Array(64);return{load:t,position:r,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function o(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function i(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var a=e("./webglAtlas.js"),u=e("./webgl.js");n.exports=r},{"./webgl.js":53,"./webglAtlas.js":54}],57:[function(e,n,t){function r(e){function n(){x=null}function t(e){x=e}function r(e){return"function"==typeof e&&k.push(e),j}function i(e){return"function"==typeof e&&P.push(e),j}function a(e){return"function"==typeof e&&N.push(e),j}function u(e){return"function"==typeof e&&L.push(e),j}function s(e){return"function"==typeof e&&E.push(e),j}function f(e){return"function"==typeof e&&b.push(e),j}function c(e){return"function"==typeof e&&w.push(e),j}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-og.byteLength){var e=new ArrayBuffer(2*g.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,g=e}};return{load:function(a){n=a,r=o(a),e=r.createProgram(v,p),n.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),h+=1,a=e.id},removeLink:function(e){h>0&&(h-=1),e.id0&&r.copyArrayPart(y,e.id*d,h*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,g,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*h),a=h-1},bringToFront:function(e){a>e.id&&r.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],60:[function(e,n,t){function r(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(P),N=n,P=t,L=e}}function n(e){d=e,v=o(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;N[t*x]=n.x,N[t*x+1]=-n.y,N[t*x+2]=e.size,P[t*x+3]=e.color}function r(e){y=!0,m=e}function i(e,n){h=e,g=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(P,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,h,g)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,h,g,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),N=new Float32Array(L),P=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:r,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],61:[function(e,n,t){function r(e,n){return{size:"number"==typeof e?e:10,color:o(n)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],62:[function(e,n,t){n.exports="0.8.1"},{}]},{},[1])(1)}); \ No newline at end of file +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=s*d-f*c,0===y?null:(x=y<0?-y/2:y/2,x=0,w=c*p-d*l,b.x=(w<0?w-x:w+x)/y,w=f*l-s*p,b.y=(w<0?w-x:w+x)/y,b)))}n.exports=r},{}],4:[function(e,n,t){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":5,"./src/degree.js":6}],5:[function(e,n,t){function r(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;i0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function f(e,n,t){if(e<1||n<1||t<1)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=p();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;i0&&a.addLink(s,r-1+o*e+u),o>0&&a.addLink(s,r+(o-1)*e+u),i>0&&a.addLink(s,r+o*e+(i-1)*e*n)}return a}function c(e){if(e<0)throw new Error("Invalid number of nodes in balanced tree");var n,t=p(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;n= 0");var n,t=p();for(n=0;n=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,u=e("ngraph.random").random(o||42),s=p();for(i=0;i=0&&t.links.splice(n,1)),r&&(n=o(e,r.links),n>=0&&r.links.splice(n,1)),U(e,"remove"),F(),!0}function h(e,n){var t,r=f(e);if(!r)return null;for(t=0;t0&&(O.fire("changed",M),M.length=0)}function P(){return Object.keys?k:j}function k(e){if("function"==typeof e)for(var n=Object.keys(A),t=0;t=0?i:-1,o);return v.push(a),a},getTotalMovement:function(){return x},removeSpring:function(e){if(e){var n=v.indexOf(e);return n>-1?(v.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return h.getBestNewPosition(e)},getBBox:function(){return h.box},gravity:function(e){return void 0!==e?(n.gravity=e,g.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,g.options({theta:e}),this):n.theta}};return o(n,w),a(w),w}n.exports=r},{"./lib/bounds":16,"./lib/createBody":17,"./lib/dragForce":18,"./lib/eulerIntegrator":19,"./lib/spring":20,"./lib/springForce":21,"ngraph.events":7,"ngraph.expose":8,"ngraph.merge":13,"ngraph.quadtreebh":22}],16:[function(e,n,t){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;u1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/u}n.exports=r},{}],20:[function(e,n,t){function r(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=r},{}],21:[function(e,n,t){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":8,"ngraph.merge":13,"ngraph.random":26}],22:[function(e,n,t){function r(e,n){return 0===n?e.quad0:1===n?e.quad1:2===n?e.quad2:3===n?e.quad3:null}function o(e,n,t){0===n?e.quad0=t:1===n?e.quad1=t:2===n?e.quad2=t:3===n&&(e.quad3=t)}n.exports=function(n){function t(){var e=h[m];return e?(e.quad0=null,e.quad1=null,e.quad2=null,e.quad3=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0):(e=new f,h[m]=e),++m,e}function i(e){var n,t,r,o,i=p,a=0,u=0,f=1,c=0,d=1;for(i[0]=y;f;){var v=i[c],h=v.body;f-=1,c+=1;var m=h!==e;h&&m?(t=h.pos.x-e.pos.x,r=h.pos.y-e.pos.y,o=Math.sqrt(t*t+r*r),0===o&&(t=(s.nextDouble()-.5)/50,r=(s.nextDouble()-.5)/50,o=Math.sqrt(t*t+r*r)),n=l*h.mass*e.mass/(o*o*o),a+=n*t,u+=n*r):m&&(t=v.massX/v.mass-e.pos.x,r=v.massY/v.mass-e.pos.y,o=Math.sqrt(t*t+r*r),0===o&&(t=(s.nextDouble()-.5)/50,r=(s.nextDouble()-.5)/50,o=Math.sqrt(t*t+r*r)),(v.right-v.left)/oi&&(i=f),ca&&(a=c)}var d=i-r,l=a-o;for(d>l?a=o+d:i=r+l,m=0,y=t(),y.left=r,y.right=i,y.top=o,y.bottom=a,n=s-1,n>=0&&(y.body=e[n]);n--;)u(e[n],y)}function u(e){for(v.reset(),v.push(y,e);!v.isEmpty();){var n=v.pop(),i=n.node,a=n.body;if(i.body){var u=i.body;if(i.body=null,d(u.pos,a.pos)){var f=3;do{var c=s.nextDouble(),l=(i.right-i.left)*c,p=(i.bottom-i.top)*c;u.pos.x=i.left+l,u.pos.y=i.top+p,f-=1}while(f>0&&d(u.pos,a.pos));if(0===f&&d(u.pos,a.pos))return}v.push(i,u),v.push(i,a)}else{var g=a.pos.x,h=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*g,i.massY=i.massY+a.mass*h;var m=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;g>w&&(m+=1,x=w,w=i.right),h>E&&(m+=2,b=E,E=i.bottom);var L=r(i,m);L?v.push(L,a):(L=t(),L.left=x,L.top=b,L.right=w,L.bottom=E,L.body=a,o(i,m,L))}}}n=n||{},n.gravity="number"==typeof n.gravity?n.gravity:-1,n.theta="number"==typeof n.theta?n.theta:.8;var s=e("ngraph.random").random(1984),f=e("./node"),c=e("./insertStack"),d=e("./isSamePosition"),l=n.gravity,p=[],v=new c,g=n.theta,h=[],m=0,y=t();return{insertBodies:a,getRoot:function(){return y},updateBodyForce:i,options:function(e){return e?("number"==typeof e.gravity&&(l=e.gravity),"number"==typeof e.theta&&(g=e.theta),this):{gravity:l,theta:g}}}}},{"./insertStack":23,"./isSamePosition":24,"./node":25,"ngraph.random":26}],23:[function(e,n,t){function r(){this.stack=[],this.popIdx=0}function o(e,n){this.node=e,this.body=n}n.exports=r,r.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new o(e,n),++this.popIdx},pop:function(){if(this.popIdx>0)return this.stack[--this.popIdx]},reset:function(){this.popIdx=0}}},{}],24:[function(e,n,t){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return t<1e-8&&r<1e-8}},{}],25:[function(e,n,t){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],26:[function(e,n,t){function r(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function o(e,n){var t=n||r();if("function"!=typeof t.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var r,o,i;for(r=e.length-1;r>0;--r)o=t.next(r+1),i=e[o],e[o]=e[r],e[r]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,r,o;for(n=e.length-1;n>0;--n)r=t.next(n+1),o=e[r],e[r]=e[n],e[n]=o;return e}}}n.exports={random:r,randomIterator:o}},{}],27:[function(e,n,t){function r(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=r},{}],28:[function(e,n,t){function r(e,n){var t=o(e);if(void 0===n)return t;for(var r=Object.keys(n),i=0;iv&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},j=function(e){p=!1,o.off("touchmove",k),o.off("touchend",j),o.off("touchcancel",j),c=null,r&&r(e)},A=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,o.on("touchmove",k),o.on("touchend",j),o.on("touchcancel",j))},_=function(e){return 1===e.touches.length?A(e,e.touches[0]):void(2===e.touches.length&&(m(e), +y(e),v=P(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),o.off("mousemove",w),o.off("mouseup",E),o.off("touchmove",k),o.off("touchend",j),o.off("touchcancel",j),N(null)}}}n.exports=r;var o=e("../Utils/documentEvents.js"),i=e("../Utils/browserInfo.js"),a=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":39,"../Utils/documentEvents.js":40,"../Utils/findElementPosition.js":41}],36:[function(e,n,t){function r(e,n){var t=o(n),r=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){r=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(r);var o=i[e.id];return o&&o.onStart&&o.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(r),r=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(r){var t=i[r.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=r;var o=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":57}],37:[function(e,n,t){function r(e,n){function t(e){return d[e]}n=o(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var r=i(n.seed),u=new a(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(e){return{x:r.next(n.maxX),y:r.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"!=typeof z||z}function r(){G=G||window.document.body,F=F||i(e,{springLength:80,springCoeff:2e-4}),O=O||a(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||s)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=f(function(){return p()},M)):(X=0,V=0,R=f(p,M)))}function g(){J||(W=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;e0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):r=e),t},getSvgRoot:function(){return t}};return i(b),b}n.exports=r;var o=e("simplesvg"),i=e("ngraph.events"),a=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":34,"ngraph.events":7,simplesvg:28}],50:[function(e,n,t){function r(e){e=c(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,r,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=i(),N=a(),P=function(e){return u()},k=function(e){return s(3014898687)},j=function(){L.updateTransform(y),N.updateTransform(y)},A=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),r&&r.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),N&&N.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){if("function"==typeof e)return P=e,this},link:function(e){if("function"==typeof e)return k=e,this},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:o,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&N.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,j()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=P(e);return r.id=t,r.position=n,r.node=e,N.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],j()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,j(),I(this),y[0]},resetScale:function(){return A(),r&&(_(),j()),this},init:function(o){var i={};if(e.preserveDrawingBuffer&&(i.preserveDrawingBuffer=!0),n=o,_(),A(),n.appendChild(t),r=t.getContext("experimental-webgl",i),!r){var a="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(a),a}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var u=e.clearColorValue;r.clearColor(u.r,u.g,u.b,u.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}L.load(r),L.updateSize(d/2,l/2),N.load(r),N.updateSize(d/2,l/2),j(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(t0&&(h-=1);var n=b[e.id];delete b[e.id],N.removeNode(n);var t=n.id;if(te.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;o=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!o(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:r,getCoordinates:a,load:u};return E}function o(e){return 0===(e&e-1)}var i=e("./texture.js");n.exports=r},{"./texture.js":52}],55:[function(e,n,t){function r(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=r},{}],56:[function(e,n,t){function r(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(A-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*N,A*N,N))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*A)}var v,g,h,m,y,x,w,b,E,L,N=18,P=o(),k=i(),j=1024,A=0,_=new Float32Array(64);return{load:t,position:r,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function o(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function i(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var a=e("./webglAtlas.js"),u=e("./webgl.js");n.exports=r},{"./webgl.js":53,"./webglAtlas.js":54}],57:[function(e,n,t){function r(e){function n(){x=null}function t(e){x=e}function r(e){return"function"==typeof e&&k.push(e),A}function i(e){return"function"==typeof e&&P.push(e),A}function a(e){return"function"==typeof e&&N.push(e),A}function u(e){return"function"==typeof e&&L.push(e),A}function s(e){return"function"==typeof e&&E.push(e),A}function f(e){return"function"==typeof e&&b.push(e),A}function c(e){return"function"==typeof e&&w.push(e),A}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oh.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,r=o(a),e=r.createProgram(v,p),n.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&r.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&r.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],60:[function(e,n,t){function r(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(P),N=n,P=t,L=e}}function n(e){d=e,v=o(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;N[t*x]=n.x,N[t*x+1]=-n.y,N[t*x+2]=e.size,P[t*x+3]=e.color}function r(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(P,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),N=new Float32Array(L),P=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:r,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],61:[function(e,n,t){function r(e,n){return{size:"number"==typeof e?e:10,color:o(n)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],62:[function(e,n,t){n.exports="0.8.1"},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/package.json b/package.json index 9b7ccd6..72a80ca 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "gulp-run": "^1.6.5", "gulp-uglify": "^1.0.2", "gulp-util": "^3.0.2", + "ngraph.remove-overlaps": "^1.0.0", "tap": "^0.4.13", "vinyl-buffer": "^1.0.0", "vinyl-source-stream": "^1.0.0" @@ -36,7 +37,7 @@ "gintersect": "0.1.0", "ngraph.centrality": "0.1.3", "ngraph.events": "0.0.3", - "ngraph.forcelayout": "0.0.21", + "ngraph.forcelayout": "0.1.2", "ngraph.fromjson": "0.1.7", "ngraph.generators": "0.0.15", "ngraph.graph": "0.0.11", From 00ff3e247153bf5f8aa827b5c362668814156c27 Mon Sep 17 00:00:00 2001 From: Andriy Kashcha Date: Mon, 8 May 2017 22:36:06 -0700 Subject: [PATCH 236/276] 0.9.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 72a80ca..38ab72a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.8.3", + "version": "0.9.0", "description": "Graph Drawing Library", "main": "src/viva", "directories": { From 00036a76c4d1b180056afed2950e881750e3c0ea Mon Sep 17 00:00:00 2001 From: Antti Kaikkonen Date: Fri, 12 May 2017 19:53:51 +0300 Subject: [PATCH 237/276] Update webglImageNodeProgram.js https://github.com/anvaka/VivaGraphJS/issues/34#issuecomment-253107796 --- src/WebGL/webglImageNodeProgram.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/WebGL/webglImageNodeProgram.js b/src/WebGL/webglImageNodeProgram.js index fc52020..f9f7ec1 100644 --- a/src/WebGL/webglImageNodeProgram.js +++ b/src/WebGL/webglImageNodeProgram.js @@ -110,27 +110,27 @@ function webglImageNodeProgram() { function position(nodeUI, pos) { var idx = nodeUI.id * ATTRIBUTES_PER_PRIMITIVE; nodes[idx] = pos.x - nodeUI.size; - nodes[idx + 1] = pos.y - nodeUI.size; + nodes[idx + 1] = -pos.y - nodeUI.size; nodes[idx + 2] = nodeUI._offset * 4; nodes[idx + 3] = pos.x + nodeUI.size; - nodes[idx + 4] = pos.y - nodeUI.size; + nodes[idx + 4] = -pos.y - nodeUI.size; nodes[idx + 5] = nodeUI._offset * 4 + 1; nodes[idx + 6] = pos.x - nodeUI.size; - nodes[idx + 7] = pos.y + nodeUI.size; + nodes[idx + 7] = -pos.y + nodeUI.size; nodes[idx + 8] = nodeUI._offset * 4 + 2; nodes[idx + 9] = pos.x - nodeUI.size; - nodes[idx + 10] = pos.y + nodeUI.size; + nodes[idx + 10] = -pos.y + nodeUI.size; nodes[idx + 11] = nodeUI._offset * 4 + 2; nodes[idx + 12] = pos.x + nodeUI.size; - nodes[idx + 13] = pos.y - nodeUI.size; + nodes[idx + 13] = -pos.y - nodeUI.size; nodes[idx + 14] = nodeUI._offset * 4 + 1; nodes[idx + 15] = pos.x + nodeUI.size; - nodes[idx + 16] = pos.y + nodeUI.size; + nodes[idx + 16] = -pos.y + nodeUI.size; nodes[idx + 17] = nodeUI._offset * 4 + 3; } From f89dcb869b8eae18eef6bd9da527e6a05a6281b2 Mon Sep 17 00:00:00 2001 From: jlazar Date: Mon, 7 Aug 2017 14:55:17 -0400 Subject: [PATCH 238/276] exposing updateSize function to graphics object --- dist/vivagraph.js | 4048 +++++++++++++++++++------------------ dist/vivagraph.min.js | 2 +- package-lock.json | 3681 +++++++++++++++++++++++++++++++++ src/View/webglGraphics.js | 6 + 4 files changed, 5715 insertions(+), 2022 deletions(-) create mode 100644 package-lock.json diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 0a7e067..0ecff26 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -3252,42 +3252,42 @@ function fail() { } },{}],32:[function(require,module,exports){ -var centrality = require('ngraph.centrality'); - -module.exports = centralityWrapper; - -function centralityWrapper() { - // TODO: This should not be a function - return { - betweennessCentrality: betweennessCentrality, - degreeCentrality: degreeCentrality - }; -} - -function betweennessCentrality(g) { - var betweenness = centrality.betweenness(g); - return toVivaGraphCentralityFormat(betweenness); -} - -function degreeCentrality(g, kind) { - var degree = centrality.degree(g, kind); - return toVivaGraphCentralityFormat(degree); -} - -function toVivaGraphCentralityFormat(centrality) { - return Object.keys(centrality).sort(byValue).map(toKeyValue); - - function byValue(x, y) { - return centrality[y] - centrality[x]; - } - - function toKeyValue(key) { - return { - key: key, - value: centrality[key] - }; - } -} +var centrality = require('ngraph.centrality'); + +module.exports = centralityWrapper; + +function centralityWrapper() { + // TODO: This should not be a function + return { + betweennessCentrality: betweennessCentrality, + degreeCentrality: degreeCentrality + }; +} + +function betweennessCentrality(g) { + var betweenness = centrality.betweenness(g); + return toVivaGraphCentralityFormat(betweenness); +} + +function degreeCentrality(g, kind) { + var degree = centrality.degree(g, kind); + return toVivaGraphCentralityFormat(degree); +} + +function toVivaGraphCentralityFormat(centrality) { + return Object.keys(centrality).sort(byValue).map(toKeyValue); + + function byValue(x, y) { + return centrality[y] - centrality[x]; + } + + function toKeyValue(key) { + return { + key: key, + value: centrality[key] + }; + } +} },{"ngraph.centrality":4}],33:[function(require,module,exports){ /** @@ -3325,651 +3325,651 @@ function operations() { }; },{}],34:[function(require,module,exports){ -/** - * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka - */ - -module.exports = domInputManager; - -var dragndrop = require('./dragndrop.js'); - -function domInputManager(graph, graphics) { - var nodeEvents = {}; - return { - /** - * Called by renderer to listen to drag-n-drop events from node. E.g. for SVG - * graphics we may listen to DOM events, whereas for WebGL the graphics - * should provide custom eventing mechanism. - * - * @param node - to be monitored. - * @param handlers - object with set of three callbacks: - * onStart: function(), - * onDrag: function(e, offset), - * onStop: function() - */ - bindDragNDrop: bindDragNDrop - }; - - function bindDragNDrop(node, handlers) { - var events; - if (handlers) { - var nodeUI = graphics.getNodeUI(node.id); - events = dragndrop(nodeUI); - if (typeof handlers.onStart === 'function') { - events.onStart(handlers.onStart); - } - if (typeof handlers.onDrag === 'function') { - events.onDrag(handlers.onDrag); - } - if (typeof handlers.onStop === 'function') { - events.onStop(handlers.onStop); - } - - nodeEvents[node.id] = events; - } else if ((events = nodeEvents[node.id])) { - events.release(); - delete nodeEvents[node.id]; - } - } -} +/** + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka + */ + +module.exports = domInputManager; + +var dragndrop = require('./dragndrop.js'); + +function domInputManager(graph, graphics) { + var nodeEvents = {}; + return { + /** + * Called by renderer to listen to drag-n-drop events from node. E.g. for SVG + * graphics we may listen to DOM events, whereas for WebGL the graphics + * should provide custom eventing mechanism. + * + * @param node - to be monitored. + * @param handlers - object with set of three callbacks: + * onStart: function(), + * onDrag: function(e, offset), + * onStop: function() + */ + bindDragNDrop: bindDragNDrop + }; + + function bindDragNDrop(node, handlers) { + var events; + if (handlers) { + var nodeUI = graphics.getNodeUI(node.id); + events = dragndrop(nodeUI); + if (typeof handlers.onStart === 'function') { + events.onStart(handlers.onStart); + } + if (typeof handlers.onDrag === 'function') { + events.onDrag(handlers.onDrag); + } + if (typeof handlers.onStop === 'function') { + events.onStop(handlers.onStop); + } + + nodeEvents[node.id] = events; + } else if ((events = nodeEvents[node.id])) { + events.release(); + delete nodeEvents[node.id]; + } + } +} },{"./dragndrop.js":35}],35:[function(require,module,exports){ -/** - * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka - */ - -module.exports = dragndrop; - -var documentEvents = require('../Utils/documentEvents.js'); -var browserInfo = require('../Utils/browserInfo.js'); -var findElementPosition = require('../Utils/findElementPosition.js'); - -// TODO: Move to input namespace -// TODO: Methods should be extracted into the prototype. This class -// does not need to consume so much memory for every tracked element -function dragndrop(element) { - var start, - drag, - end, - scroll, - prevSelectStart, - prevDragStart, - - startX = 0, - startY = 0, - dragObject, - touchInProgress = false, - pinchZoomLength = 0, - - getMousePos = function (e) { - var posx = 0, - posy = 0; - - e = e || window.event; - - if (e.pageX || e.pageY) { - posx = e.pageX; - posy = e.pageY; - } else if (e.clientX || e.clientY) { - posx = e.clientX + window.document.body.scrollLeft + window.document.documentElement.scrollLeft; - posy = e.clientY + window.document.body.scrollTop + window.document.documentElement.scrollTop; - } - - return [posx, posy]; - }, - - move = function (e, clientX, clientY) { - if (drag) { - drag(e, {x : clientX - startX, y : clientY - startY }); - } - - startX = clientX; - startY = clientY; - }, - - stopPropagation = function (e) { - if (e.stopPropagation) { e.stopPropagation(); } else { e.cancelBubble = true; } - }, - preventDefault = function (e) { - if (e.preventDefault) { e.preventDefault(); } - }, - - handleDisabledEvent = function (e) { - stopPropagation(e); - return false; - }, - - handleMouseMove = function (e) { - e = e || window.event; - - move(e, e.clientX, e.clientY); - }, - - handleMouseDown = function (e) { - e = e || window.event; - if (touchInProgress) { - // modern browsers will fire mousedown for touch events too - // we do not want this, since touch is handled separately. - stopPropagation(e); - return false; - } - // for IE, left click == 1 - // for Firefox, left click == 0 - var isLeftButton = ((e.button === 1 && window.event !== null) || e.button === 0); - - if (isLeftButton) { - startX = e.clientX; - startY = e.clientY; - - // TODO: bump zIndex? - dragObject = e.target || e.srcElement; - - if (start) { start(e, {x: startX, y : startY}); } - - documentEvents.on('mousemove', handleMouseMove); - documentEvents.on('mouseup', handleMouseUp); - - - stopPropagation(e); - // TODO: What if event already there? Not bullet proof: - prevSelectStart = window.document.onselectstart; - prevDragStart = window.document.ondragstart; - - window.document.onselectstart = handleDisabledEvent; - dragObject.ondragstart = handleDisabledEvent; - - // prevent text selection (except IE) - return false; - } - }, - - handleMouseUp = function (e) { - e = e || window.event; - - documentEvents.off('mousemove', handleMouseMove); - documentEvents.off('mouseup', handleMouseUp); - - window.document.onselectstart = prevSelectStart; - dragObject.ondragstart = prevDragStart; - dragObject = null; - if (end) { end(e); } - }, - - handleMouseWheel = function (e) { - if (typeof scroll !== 'function') { - return; - } - - e = e || window.event; - if (e.preventDefault) { - e.preventDefault(); - } - - e.returnValue = false; - var delta, - mousePos = getMousePos(e), - elementOffset = findElementPosition(element), - relMousePos = { - x: mousePos[0] - elementOffset[0], - y: mousePos[1] - elementOffset[1] - }; - - if (e.wheelDelta) { - delta = e.wheelDelta / 360; // Chrome/Safari - } else { - delta = e.detail / -9; // Mozilla - } - - scroll(e, delta, relMousePos); - }, - - updateScrollEvents = function (scrollCallback) { - if (!scroll && scrollCallback) { - // client is interested in scrolling. Start listening to events: - if (browserInfo.browser === 'webkit') { - element.addEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari - } else { - element.addEventListener('DOMMouseScroll', handleMouseWheel, false); // Others - } - } else if (scroll && !scrollCallback) { - if (browserInfo.browser === 'webkit') { - element.removeEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari - } else { - element.removeEventListener('DOMMouseScroll', handleMouseWheel, false); // Others - } - } - - scroll = scrollCallback; - }, - - getPinchZoomLength = function(finger1, finger2) { - return (finger1.clientX - finger2.clientX) * (finger1.clientX - finger2.clientX) + - (finger1.clientY - finger2.clientY) * (finger1.clientY - finger2.clientY); - }, - - handleTouchMove = function (e) { - if (e.touches.length === 1) { - stopPropagation(e); - - var touch = e.touches[0]; - move(e, touch.clientX, touch.clientY); - } else if (e.touches.length === 2) { - // it's a zoom: - var currentPinchLength = getPinchZoomLength(e.touches[0], e.touches[1]); - var delta = 0; - if (currentPinchLength < pinchZoomLength) { - delta = -1; - } else if (currentPinchLength > pinchZoomLength) { - delta = 1; - } - scroll(e, delta, {x: e.touches[0].clientX, y: e.touches[0].clientY}); - pinchZoomLength = currentPinchLength; - stopPropagation(e); - preventDefault(e); - } - }, - - handleTouchEnd = function (e) { - touchInProgress = false; - documentEvents.off('touchmove', handleTouchMove); - documentEvents.off('touchend', handleTouchEnd); - documentEvents.off('touchcancel', handleTouchEnd); - dragObject = null; - if (end) { end(e); } - }, - - handleSignleFingerTouch = function (e, touch) { - stopPropagation(e); - preventDefault(e); - - startX = touch.clientX; - startY = touch.clientY; - - dragObject = e.target || e.srcElement; - - if (start) { start(e, {x: startX, y : startY}); } - // TODO: can I enter into the state when touch is in progress - // but it's still a single finger touch? - if (!touchInProgress) { - touchInProgress = true; - documentEvents.on('touchmove', handleTouchMove); - documentEvents.on('touchend', handleTouchEnd); - documentEvents.on('touchcancel', handleTouchEnd); - } - }, - - handleTouchStart = function (e) { - if (e.touches.length === 1) { - return handleSignleFingerTouch(e, e.touches[0]); - } else if (e.touches.length === 2) { - // handleTouchMove() will care about pinch zoom. - stopPropagation(e); - preventDefault(e); - - pinchZoomLength = getPinchZoomLength(e.touches[0], e.touches[1]); - - } - // don't care about the rest. - }; - - - element.addEventListener('mousedown', handleMouseDown); - element.addEventListener('touchstart', handleTouchStart); - - return { - onStart : function (callback) { - start = callback; - return this; - }, - - onDrag : function (callback) { - drag = callback; - return this; - }, - - onStop : function (callback) { - end = callback; - return this; - }, - - /** - * Occurs when mouse wheel event happens. callback = function(e, scrollDelta, scrollPoint); - */ - onScroll : function (callback) { - updateScrollEvents(callback); - return this; - }, - - release : function () { - // TODO: could be unsafe. We might wanna release dragObject, etc. - element.removeEventListener('mousedown', handleMouseDown); - element.removeEventListener('touchstart', handleTouchStart); - - documentEvents.off('mousemove', handleMouseMove); - documentEvents.off('mouseup', handleMouseUp); - documentEvents.off('touchmove', handleTouchMove); - documentEvents.off('touchend', handleTouchEnd); - documentEvents.off('touchcancel', handleTouchEnd); - - updateScrollEvents(null); - } - }; -} +/** + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka + */ + +module.exports = dragndrop; + +var documentEvents = require('../Utils/documentEvents.js'); +var browserInfo = require('../Utils/browserInfo.js'); +var findElementPosition = require('../Utils/findElementPosition.js'); + +// TODO: Move to input namespace +// TODO: Methods should be extracted into the prototype. This class +// does not need to consume so much memory for every tracked element +function dragndrop(element) { + var start, + drag, + end, + scroll, + prevSelectStart, + prevDragStart, + + startX = 0, + startY = 0, + dragObject, + touchInProgress = false, + pinchZoomLength = 0, + + getMousePos = function (e) { + var posx = 0, + posy = 0; + + e = e || window.event; + + if (e.pageX || e.pageY) { + posx = e.pageX; + posy = e.pageY; + } else if (e.clientX || e.clientY) { + posx = e.clientX + window.document.body.scrollLeft + window.document.documentElement.scrollLeft; + posy = e.clientY + window.document.body.scrollTop + window.document.documentElement.scrollTop; + } + + return [posx, posy]; + }, + + move = function (e, clientX, clientY) { + if (drag) { + drag(e, {x : clientX - startX, y : clientY - startY }); + } + + startX = clientX; + startY = clientY; + }, + + stopPropagation = function (e) { + if (e.stopPropagation) { e.stopPropagation(); } else { e.cancelBubble = true; } + }, + preventDefault = function (e) { + if (e.preventDefault) { e.preventDefault(); } + }, + + handleDisabledEvent = function (e) { + stopPropagation(e); + return false; + }, + + handleMouseMove = function (e) { + e = e || window.event; + + move(e, e.clientX, e.clientY); + }, + + handleMouseDown = function (e) { + e = e || window.event; + if (touchInProgress) { + // modern browsers will fire mousedown for touch events too + // we do not want this, since touch is handled separately. + stopPropagation(e); + return false; + } + // for IE, left click == 1 + // for Firefox, left click == 0 + var isLeftButton = ((e.button === 1 && window.event !== null) || e.button === 0); + + if (isLeftButton) { + startX = e.clientX; + startY = e.clientY; + + // TODO: bump zIndex? + dragObject = e.target || e.srcElement; + + if (start) { start(e, {x: startX, y : startY}); } + + documentEvents.on('mousemove', handleMouseMove); + documentEvents.on('mouseup', handleMouseUp); + + + stopPropagation(e); + // TODO: What if event already there? Not bullet proof: + prevSelectStart = window.document.onselectstart; + prevDragStart = window.document.ondragstart; + + window.document.onselectstart = handleDisabledEvent; + dragObject.ondragstart = handleDisabledEvent; + + // prevent text selection (except IE) + return false; + } + }, + + handleMouseUp = function (e) { + e = e || window.event; + + documentEvents.off('mousemove', handleMouseMove); + documentEvents.off('mouseup', handleMouseUp); + + window.document.onselectstart = prevSelectStart; + dragObject.ondragstart = prevDragStart; + dragObject = null; + if (end) { end(e); } + }, + + handleMouseWheel = function (e) { + if (typeof scroll !== 'function') { + return; + } + + e = e || window.event; + if (e.preventDefault) { + e.preventDefault(); + } + + e.returnValue = false; + var delta, + mousePos = getMousePos(e), + elementOffset = findElementPosition(element), + relMousePos = { + x: mousePos[0] - elementOffset[0], + y: mousePos[1] - elementOffset[1] + }; + + if (e.wheelDelta) { + delta = e.wheelDelta / 360; // Chrome/Safari + } else { + delta = e.detail / -9; // Mozilla + } + + scroll(e, delta, relMousePos); + }, + + updateScrollEvents = function (scrollCallback) { + if (!scroll && scrollCallback) { + // client is interested in scrolling. Start listening to events: + if (browserInfo.browser === 'webkit') { + element.addEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari + } else { + element.addEventListener('DOMMouseScroll', handleMouseWheel, false); // Others + } + } else if (scroll && !scrollCallback) { + if (browserInfo.browser === 'webkit') { + element.removeEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari + } else { + element.removeEventListener('DOMMouseScroll', handleMouseWheel, false); // Others + } + } + + scroll = scrollCallback; + }, + + getPinchZoomLength = function(finger1, finger2) { + return (finger1.clientX - finger2.clientX) * (finger1.clientX - finger2.clientX) + + (finger1.clientY - finger2.clientY) * (finger1.clientY - finger2.clientY); + }, + + handleTouchMove = function (e) { + if (e.touches.length === 1) { + stopPropagation(e); + + var touch = e.touches[0]; + move(e, touch.clientX, touch.clientY); + } else if (e.touches.length === 2) { + // it's a zoom: + var currentPinchLength = getPinchZoomLength(e.touches[0], e.touches[1]); + var delta = 0; + if (currentPinchLength < pinchZoomLength) { + delta = -1; + } else if (currentPinchLength > pinchZoomLength) { + delta = 1; + } + scroll(e, delta, {x: e.touches[0].clientX, y: e.touches[0].clientY}); + pinchZoomLength = currentPinchLength; + stopPropagation(e); + preventDefault(e); + } + }, + + handleTouchEnd = function (e) { + touchInProgress = false; + documentEvents.off('touchmove', handleTouchMove); + documentEvents.off('touchend', handleTouchEnd); + documentEvents.off('touchcancel', handleTouchEnd); + dragObject = null; + if (end) { end(e); } + }, + + handleSignleFingerTouch = function (e, touch) { + stopPropagation(e); + preventDefault(e); + + startX = touch.clientX; + startY = touch.clientY; + + dragObject = e.target || e.srcElement; + + if (start) { start(e, {x: startX, y : startY}); } + // TODO: can I enter into the state when touch is in progress + // but it's still a single finger touch? + if (!touchInProgress) { + touchInProgress = true; + documentEvents.on('touchmove', handleTouchMove); + documentEvents.on('touchend', handleTouchEnd); + documentEvents.on('touchcancel', handleTouchEnd); + } + }, + + handleTouchStart = function (e) { + if (e.touches.length === 1) { + return handleSignleFingerTouch(e, e.touches[0]); + } else if (e.touches.length === 2) { + // handleTouchMove() will care about pinch zoom. + stopPropagation(e); + preventDefault(e); + + pinchZoomLength = getPinchZoomLength(e.touches[0], e.touches[1]); + + } + // don't care about the rest. + }; + + + element.addEventListener('mousedown', handleMouseDown); + element.addEventListener('touchstart', handleTouchStart); + + return { + onStart : function (callback) { + start = callback; + return this; + }, + + onDrag : function (callback) { + drag = callback; + return this; + }, + + onStop : function (callback) { + end = callback; + return this; + }, + + /** + * Occurs when mouse wheel event happens. callback = function(e, scrollDelta, scrollPoint); + */ + onScroll : function (callback) { + updateScrollEvents(callback); + return this; + }, + + release : function () { + // TODO: could be unsafe. We might wanna release dragObject, etc. + element.removeEventListener('mousedown', handleMouseDown); + element.removeEventListener('touchstart', handleTouchStart); + + documentEvents.off('mousemove', handleMouseMove); + documentEvents.off('mouseup', handleMouseUp); + documentEvents.off('touchmove', handleTouchMove); + documentEvents.off('touchend', handleTouchEnd); + documentEvents.off('touchcancel', handleTouchEnd); + + updateScrollEvents(null); + } + }; +} },{"../Utils/browserInfo.js":39,"../Utils/documentEvents.js":40,"../Utils/findElementPosition.js":41}],36:[function(require,module,exports){ -/** - * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka - */ - -module.exports = webglInputManager; - -var createInputEvents = require('../WebGL/webglInputEvents.js'); - -function webglInputManager(graph, graphics) { - var inputEvents = createInputEvents(graphics), - draggedNode = null, - internalHandlers = {}, - pos = {x : 0, y : 0}; - - inputEvents.mouseDown(function (node, e) { - draggedNode = node; - pos.x = e.clientX; - pos.y = e.clientY; - - inputEvents.mouseCapture(draggedNode); - - var handlers = internalHandlers[node.id]; - if (handlers && handlers.onStart) { - handlers.onStart(e, pos); - } - - return true; - }).mouseUp(function (node) { - inputEvents.releaseMouseCapture(draggedNode); - - draggedNode = null; - var handlers = internalHandlers[node.id]; - if (handlers && handlers.onStop) { - handlers.onStop(); - } - return true; - }).mouseMove(function (node, e) { - if (draggedNode) { - var handlers = internalHandlers[draggedNode.id]; - if (handlers && handlers.onDrag) { - handlers.onDrag(e, {x : e.clientX - pos.x, y : e.clientY - pos.y }); - } - - pos.x = e.clientX; - pos.y = e.clientY; - return true; - } - }); - - return { - /** - * Called by renderer to listen to drag-n-drop events from node. E.g. for SVG - * graphics we may listen to DOM events, whereas for WebGL we graphics - * should provide custom eventing mechanism. - * - * @param node - to be monitored. - * @param handlers - object with set of three callbacks: - * onStart: function(), - * onDrag: function(e, offset), - * onStop: function() - */ - bindDragNDrop : function (node, handlers) { - internalHandlers[node.id] = handlers; - if (!handlers) { - delete internalHandlers[node.id]; - } - } - }; -} +/** + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka + */ + +module.exports = webglInputManager; + +var createInputEvents = require('../WebGL/webglInputEvents.js'); + +function webglInputManager(graph, graphics) { + var inputEvents = createInputEvents(graphics), + draggedNode = null, + internalHandlers = {}, + pos = {x : 0, y : 0}; + + inputEvents.mouseDown(function (node, e) { + draggedNode = node; + pos.x = e.clientX; + pos.y = e.clientY; + + inputEvents.mouseCapture(draggedNode); + + var handlers = internalHandlers[node.id]; + if (handlers && handlers.onStart) { + handlers.onStart(e, pos); + } + + return true; + }).mouseUp(function (node) { + inputEvents.releaseMouseCapture(draggedNode); + + draggedNode = null; + var handlers = internalHandlers[node.id]; + if (handlers && handlers.onStop) { + handlers.onStop(); + } + return true; + }).mouseMove(function (node, e) { + if (draggedNode) { + var handlers = internalHandlers[draggedNode.id]; + if (handlers && handlers.onDrag) { + handlers.onDrag(e, {x : e.clientX - pos.x, y : e.clientY - pos.y }); + } + + pos.x = e.clientX; + pos.y = e.clientY; + return true; + } + }); + + return { + /** + * Called by renderer to listen to drag-n-drop events from node. E.g. for SVG + * graphics we may listen to DOM events, whereas for WebGL we graphics + * should provide custom eventing mechanism. + * + * @param node - to be monitored. + * @param handlers - object with set of three callbacks: + * onStart: function(), + * onDrag: function(e, offset), + * onStop: function() + */ + bindDragNDrop : function (node, handlers) { + internalHandlers[node.id] = handlers; + if (!handlers) { + delete internalHandlers[node.id]; + } + } + }; +} },{"../WebGL/webglInputEvents.js":57}],37:[function(require,module,exports){ -module.exports = constant; - -var merge = require('ngraph.merge'); -var random = require('ngraph.random').random; -var Rect = require('../Utils/rect.js'); - -/** - * Does not really perform any layouting algorithm but is compliant - * with renderer interface. Allowing clients to provide specific positioning - * callback and get static layout of the graph - * - * @param {Viva.Graph.graph} graph to layout - * @param {Object} userSettings - */ -function constant(graph, userSettings) { - userSettings = merge(userSettings, { - maxX : 1024, - maxY : 1024, - seed : 'Deterministic randomness made me do this' - }); - // This class simply follows API, it does not use some of the arguments: - /*jshint unused: false */ - var rand = random(userSettings.seed), - graphRect = new Rect(Number.MAX_VALUE, Number.MAX_VALUE, Number.MIN_VALUE, Number.MIN_VALUE), - layoutLinks = {}, - - placeNodeCallback = function (node) { - return { - x: rand.next(userSettings.maxX), - y: rand.next(userSettings.maxY) - }; - }, - - updateGraphRect = function (position, graphRect) { - if (position.x < graphRect.x1) { graphRect.x1 = position.x; } - if (position.x > graphRect.x2) { graphRect.x2 = position.x; } - if (position.y < graphRect.y1) { graphRect.y1 = position.y; } - if (position.y > graphRect.y2) { graphRect.y2 = position.y; } - }, - - layoutNodes = typeof Object.create === 'function' ? Object.create(null) : {}, - - ensureNodeInitialized = function (node) { - layoutNodes[node.id] = placeNodeCallback(node); - updateGraphRect(layoutNodes[node.id], graphRect); - }, - - updateNodePositions = function () { - if (graph.getNodesCount() === 0) { return; } - - graphRect.x1 = Number.MAX_VALUE; - graphRect.y1 = Number.MAX_VALUE; - graphRect.x2 = Number.MIN_VALUE; - graphRect.y2 = Number.MIN_VALUE; - - graph.forEachNode(ensureNodeInitialized); - }, - - ensureLinkInitialized = function (link) { - layoutLinks[link.id] = link; - }, - - onGraphChanged = function(changes) { - for (var i = 0; i < changes.length; ++i) { - var change = changes[i]; - if (change.node) { - if (change.changeType === 'add') { - ensureNodeInitialized(change.node); - } else { - delete layoutNodes[change.node.id]; - } - } if (change.link) { - if (change.changeType === 'add') { - ensureLinkInitialized(change.link); - } else { - delete layoutLinks[change.link.id]; - } - } - } - }; - - graph.forEachNode(ensureNodeInitialized); - graph.forEachLink(ensureLinkInitialized); - graph.on('changed', onGraphChanged); - - return { - /** - * Attempts to layout graph within given number of iterations. - * - * @param {integer} [iterationsCount] number of algorithm's iterations. - * The constant layout ignores this parameter. - */ - run : function (iterationsCount) { - this.step(); - }, - - /** - * One step of layout algorithm. - */ - step : function () { - updateNodePositions(); - - return true; // no need to continue. - }, - - /** - * Returns rectangle structure {x1, y1, x2, y2}, which represents - * current space occupied by graph. - */ - getGraphRect : function () { - return graphRect; - }, - - /** - * Request to release all resources - */ - dispose : function () { - graph.off('change', onGraphChanged); - }, - - /* - * Checks whether given node is pinned; all nodes in this layout are pinned. - */ - isNodePinned: function (node) { - return true; - }, - - /* - * Requests layout algorithm to pin/unpin node to its current position - * Pinned nodes should not be affected by layout algorithm and always - * remain at their position - */ - pinNode: function (node, isPinned) { - // noop - }, - - /* - * Gets position of a node by its id. If node was not seen by this - * layout algorithm undefined value is returned; - */ - getNodePosition: getNodePosition, - - /** - * Returns {from, to} position of a link. - */ - getLinkPosition: function (linkId) { - var link = layoutLinks[linkId]; - return { - from : getNodePosition(link.fromId), - to : getNodePosition(link.toId) - }; - }, - - /** - * Sets position of a node to a given coordinates - */ - setNodePosition: function (nodeId, x, y) { - var pos = layoutNodes[nodeId]; - if (pos) { - pos.x = x; - pos.y = y; - } - }, - - // Layout specific methods: - - /** - * Based on argument either update default node placement callback or - * attempts to place given node using current placement callback. - * Setting new node callback triggers position update for all nodes. - * - * @param {Object} newPlaceNodeCallbackOrNode - if it is a function then - * default node placement callback is replaced with new one. Node placement - * callback has a form of function (node) {}, and is expected to return an - * object with x and y properties set to numbers. - * - * Otherwise if it's not a function the argument is treated as graph node - * and current node placement callback will be used to place it. - */ - placeNode : function (newPlaceNodeCallbackOrNode) { - if (typeof newPlaceNodeCallbackOrNode === 'function') { - placeNodeCallback = newPlaceNodeCallbackOrNode; - updateNodePositions(); - return this; - } - - // it is not a request to update placeNodeCallback, trying to place - // a node using current callback: - return placeNodeCallback(newPlaceNodeCallbackOrNode); - } - - }; - - function getNodePosition(nodeId) { - return layoutNodes[nodeId]; - } -} +module.exports = constant; + +var merge = require('ngraph.merge'); +var random = require('ngraph.random').random; +var Rect = require('../Utils/rect.js'); + +/** + * Does not really perform any layouting algorithm but is compliant + * with renderer interface. Allowing clients to provide specific positioning + * callback and get static layout of the graph + * + * @param {Viva.Graph.graph} graph to layout + * @param {Object} userSettings + */ +function constant(graph, userSettings) { + userSettings = merge(userSettings, { + maxX : 1024, + maxY : 1024, + seed : 'Deterministic randomness made me do this' + }); + // This class simply follows API, it does not use some of the arguments: + /*jshint unused: false */ + var rand = random(userSettings.seed), + graphRect = new Rect(Number.MAX_VALUE, Number.MAX_VALUE, Number.MIN_VALUE, Number.MIN_VALUE), + layoutLinks = {}, + + placeNodeCallback = function (node) { + return { + x: rand.next(userSettings.maxX), + y: rand.next(userSettings.maxY) + }; + }, + + updateGraphRect = function (position, graphRect) { + if (position.x < graphRect.x1) { graphRect.x1 = position.x; } + if (position.x > graphRect.x2) { graphRect.x2 = position.x; } + if (position.y < graphRect.y1) { graphRect.y1 = position.y; } + if (position.y > graphRect.y2) { graphRect.y2 = position.y; } + }, + + layoutNodes = typeof Object.create === 'function' ? Object.create(null) : {}, + + ensureNodeInitialized = function (node) { + layoutNodes[node.id] = placeNodeCallback(node); + updateGraphRect(layoutNodes[node.id], graphRect); + }, + + updateNodePositions = function () { + if (graph.getNodesCount() === 0) { return; } + + graphRect.x1 = Number.MAX_VALUE; + graphRect.y1 = Number.MAX_VALUE; + graphRect.x2 = Number.MIN_VALUE; + graphRect.y2 = Number.MIN_VALUE; + + graph.forEachNode(ensureNodeInitialized); + }, + + ensureLinkInitialized = function (link) { + layoutLinks[link.id] = link; + }, + + onGraphChanged = function(changes) { + for (var i = 0; i < changes.length; ++i) { + var change = changes[i]; + if (change.node) { + if (change.changeType === 'add') { + ensureNodeInitialized(change.node); + } else { + delete layoutNodes[change.node.id]; + } + } if (change.link) { + if (change.changeType === 'add') { + ensureLinkInitialized(change.link); + } else { + delete layoutLinks[change.link.id]; + } + } + } + }; + + graph.forEachNode(ensureNodeInitialized); + graph.forEachLink(ensureLinkInitialized); + graph.on('changed', onGraphChanged); + + return { + /** + * Attempts to layout graph within given number of iterations. + * + * @param {integer} [iterationsCount] number of algorithm's iterations. + * The constant layout ignores this parameter. + */ + run : function (iterationsCount) { + this.step(); + }, + + /** + * One step of layout algorithm. + */ + step : function () { + updateNodePositions(); + + return true; // no need to continue. + }, + + /** + * Returns rectangle structure {x1, y1, x2, y2}, which represents + * current space occupied by graph. + */ + getGraphRect : function () { + return graphRect; + }, + + /** + * Request to release all resources + */ + dispose : function () { + graph.off('change', onGraphChanged); + }, + + /* + * Checks whether given node is pinned; all nodes in this layout are pinned. + */ + isNodePinned: function (node) { + return true; + }, + + /* + * Requests layout algorithm to pin/unpin node to its current position + * Pinned nodes should not be affected by layout algorithm and always + * remain at their position + */ + pinNode: function (node, isPinned) { + // noop + }, + + /* + * Gets position of a node by its id. If node was not seen by this + * layout algorithm undefined value is returned; + */ + getNodePosition: getNodePosition, + + /** + * Returns {from, to} position of a link. + */ + getLinkPosition: function (linkId) { + var link = layoutLinks[linkId]; + return { + from : getNodePosition(link.fromId), + to : getNodePosition(link.toId) + }; + }, + + /** + * Sets position of a node to a given coordinates + */ + setNodePosition: function (nodeId, x, y) { + var pos = layoutNodes[nodeId]; + if (pos) { + pos.x = x; + pos.y = y; + } + }, + + // Layout specific methods: + + /** + * Based on argument either update default node placement callback or + * attempts to place given node using current placement callback. + * Setting new node callback triggers position update for all nodes. + * + * @param {Object} newPlaceNodeCallbackOrNode - if it is a function then + * default node placement callback is replaced with new one. Node placement + * callback has a form of function (node) {}, and is expected to return an + * object with x and y properties set to numbers. + * + * Otherwise if it's not a function the argument is treated as graph node + * and current node placement callback will be used to place it. + */ + placeNode : function (newPlaceNodeCallbackOrNode) { + if (typeof newPlaceNodeCallbackOrNode === 'function') { + placeNodeCallback = newPlaceNodeCallbackOrNode; + updateNodePositions(); + return this; + } + + // it is not a request to update placeNodeCallback, trying to place + // a node using current callback: + return placeNodeCallback(newPlaceNodeCallbackOrNode); + } + + }; + + function getNodePosition(nodeId) { + return layoutNodes[nodeId]; + } +} },{"../Utils/rect.js":45,"ngraph.merge":13,"ngraph.random":26}],38:[function(require,module,exports){ -/** - * This module provides compatibility layer with 0.6.x library. It will be - * removed in the next version - */ - -var events = require('ngraph.events'); - -module.exports = backwardCompatibleEvents; - -function backwardCompatibleEvents(g) { - console.log("This method is deprecated. Please use Viva.events() instead"); - - if (!g) { - return g; - } - - var eventsDefined = (g.on !== undefined) || - (g.off !== undefined) || - (g.fire !== undefined); - - if (eventsDefined) { - // events already defined, ignore - return { - extend: function() { - return g; - }, - on: g.on, - stop: g.off - }; - } - - return { - extend: extend, - on: g.on, - stop: g.off - }; - - function extend() { - var backwardCompatible = events(g); - backwardCompatible.addEventListener = backwardCompatible.on; - return backwardCompatible; - } -} +/** + * This module provides compatibility layer with 0.6.x library. It will be + * removed in the next version + */ + +var events = require('ngraph.events'); + +module.exports = backwardCompatibleEvents; + +function backwardCompatibleEvents(g) { + console.log("This method is deprecated. Please use Viva.events() instead"); + + if (!g) { + return g; + } + + var eventsDefined = (g.on !== undefined) || + (g.off !== undefined) || + (g.fire !== undefined); + + if (eventsDefined) { + // events already defined, ignore + return { + extend: function() { + return g; + }, + on: g.on, + stop: g.off + }; + } + + return { + extend: extend, + on: g.on, + stop: g.off + }; + + function extend() { + var backwardCompatible = events(g); + backwardCompatible.addEventListener = backwardCompatible.on; + return backwardCompatible; + } +} },{"ngraph.events":7}],39:[function(require,module,exports){ module.exports = browserInfo(); @@ -4001,47 +4001,47 @@ function browserInfo() { } },{}],40:[function(require,module,exports){ -var nullEvents = require('./nullEvents.js'); - -module.exports = createDocumentEvents(); - -function createDocumentEvents() { - if (typeof document === undefined) { - return nullEvents; - } - - return { - on: on, - off: off - }; -} - -function on(eventName, handler) { - document.addEventListener(eventName, handler); -} - -function off(eventName, handler) { - document.removeEventListener(eventName, handler); -} +var nullEvents = require('./nullEvents.js'); + +module.exports = createDocumentEvents(); + +function createDocumentEvents() { + if (typeof document === undefined) { + return nullEvents; + } + + return { + on: on, + off: off + }; +} + +function on(eventName, handler) { + document.addEventListener(eventName, handler); +} + +function off(eventName, handler) { + document.removeEventListener(eventName, handler); +} },{"./nullEvents.js":44}],41:[function(require,module,exports){ -/** - * Finds the absolute position of an element on a page - */ -module.exports = findElementPosition; - -function findElementPosition(obj) { - var curleft = 0, - curtop = 0; - if (obj.offsetParent) { - do { - curleft += obj.offsetLeft; - curtop += obj.offsetTop; - } while ((obj = obj.offsetParent) !== null); - } - - return [curleft, curtop]; -} +/** + * Finds the absolute position of an element on a page + */ +module.exports = findElementPosition; + +function findElementPosition(obj) { + var curleft = 0, + curtop = 0; + if (obj.offsetParent) { + do { + curleft += obj.offsetLeft; + curtop += obj.offsetTop; + } while ((obj = obj.offsetParent) !== null); + } + + return [curleft, curtop]; +} },{}],42:[function(require,module,exports){ module.exports = getDimension; @@ -4066,42 +4066,42 @@ function getDimension(container) { } },{}],43:[function(require,module,exports){ -var intersect = require('gintersect'); - -module.exports = intersectRect; - -function intersectRect(left, top, right, bottom, x1, y1, x2, y2) { - return intersect(left, top, left, bottom, x1, y1, x2, y2) || - intersect(left, bottom, right, bottom, x1, y1, x2, y2) || - intersect(right, bottom, right, top, x1, y1, x2, y2) || - intersect(right, top, left, top, x1, y1, x2, y2); -} +var intersect = require('gintersect'); + +module.exports = intersectRect; + +function intersectRect(left, top, right, bottom, x1, y1, x2, y2) { + return intersect(left, top, left, bottom, x1, y1, x2, y2) || + intersect(left, bottom, right, bottom, x1, y1, x2, y2) || + intersect(right, bottom, right, top, x1, y1, x2, y2) || + intersect(right, top, left, top, x1, y1, x2, y2); +} },{"gintersect":3}],44:[function(require,module,exports){ -module.exports = createNullEvents(); - -function createNullEvents() { - return { - on: noop, - off: noop, - stop: noop - }; -} - -function noop() { } +module.exports = createNullEvents(); + +function createNullEvents() { + return { + on: noop, + off: noop, + stop: noop + }; +} + +function noop() { } },{}],45:[function(require,module,exports){ -module.exports = Rect; - -/** - * Very generic rectangle. - */ -function Rect (x1, y1, x2, y2) { - this.x1 = x1 || 0; - this.y1 = y1 || 0; - this.x2 = x2 || 0; - this.y2 = y2 || 0; -} +module.exports = Rect; + +/** + * Very generic rectangle. + */ +function Rect (x1, y1, x2, y2) { + this.x1 = x1 || 0; + this.y1 = y1 || 0; + this.x2 = x2 || 0; + this.y2 = y2 || 0; +} },{}],46:[function(require,module,exports){ (function (global){ @@ -4200,29 +4200,29 @@ function noop() {} }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{}],47:[function(require,module,exports){ -var nullEvents = require('./nullEvents.js'); - -module.exports = createDocumentEvents(); - -function createDocumentEvents() { - if (typeof window === 'undefined') { - return nullEvents; - } - - return { - on: on, - off: off - }; -} - -function on(eventName, handler) { - window.addEventListener(eventName, handler); -} - -function off(eventName, handler) { - window.removeEventListener(eventName, handler); -} - +var nullEvents = require('./nullEvents.js'); + +module.exports = createDocumentEvents(); + +function createDocumentEvents() { + if (typeof window === 'undefined') { + return nullEvents; + } + + return { + on: on, + off: off + }; +} + +function on(eventName, handler) { + window.addEventListener(eventName, handler); +} + +function off(eventName, handler) { + window.removeEventListener(eventName, handler); +} + },{"./nullEvents.js":44}],48:[function(require,module,exports){ /** @@ -5356,6 +5356,12 @@ function webglGraphics(options) { return this; }, + /** + * Resizes the graphic without resetting the scale. + * Useful with viva graph in a dynamic container + */ + updateSize: updateSize, + /** * Called by Viva.Graph.View.renderer to let concrete graphic output * provider prepare to render. @@ -5646,1282 +5652,1282 @@ function webglGraphics(options) { } },{"../Input/webglInputManager.js":36,"../WebGL/webglLine.js":58,"../WebGL/webglLinkProgram.js":59,"../WebGL/webglNodeProgram.js":60,"../WebGL/webglSquare.js":61,"ngraph.events":7,"ngraph.merge":13}],51:[function(require,module,exports){ -module.exports = parseColor; - -function parseColor(color) { - var parsedColor = 0x009ee8ff; - - if (typeof color === 'string' && color) { - if (color.length === 4) { // #rgb - color = color.replace(/([^#])/g, '$1$1'); // duplicate each letter except first #. - } - if (color.length === 9) { // #rrggbbaa - parsedColor = parseInt(color.substr(1), 16); - } else if (color.length === 7) { // or #rrggbb. - parsedColor = (parseInt(color.substr(1), 16) << 8) | 0xff; - } else { - throw 'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: ' + color; - } - } else if (typeof color === 'number') { - parsedColor = color; - } - - return parsedColor; -} +module.exports = parseColor; + +function parseColor(color) { + var parsedColor = 0x009ee8ff; + + if (typeof color === 'string' && color) { + if (color.length === 4) { // #rgb + color = color.replace(/([^#])/g, '$1$1'); // duplicate each letter except first #. + } + if (color.length === 9) { // #rrggbbaa + parsedColor = parseInt(color.substr(1), 16); + } else if (color.length === 7) { // or #rrggbb. + parsedColor = (parseInt(color.substr(1), 16) << 8) | 0xff; + } else { + throw 'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: ' + color; + } + } else if (typeof color === 'number') { + parsedColor = color; + } + + return parsedColor; +} },{}],52:[function(require,module,exports){ -module.exports = Texture; - -/** - * Single texture in the webglAtlas. - */ -function Texture(size) { - this.canvas = window.document.createElement("canvas"); - this.ctx = this.canvas.getContext("2d"); - this.isDirty = false; - this.canvas.width = this.canvas.height = size; -} +module.exports = Texture; + +/** + * Single texture in the webglAtlas. + */ +function Texture(size) { + this.canvas = window.document.createElement("canvas"); + this.ctx = this.canvas.getContext("2d"); + this.isDirty = false; + this.canvas.width = this.canvas.height = size; +} },{}],53:[function(require,module,exports){ -/** - * @fileOverview Utility functions for webgl rendering. - * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com - */ - -module.exports = webgl; - -function webgl(gl) { - - return { - createProgram: createProgram, - extendArray: extendArray, - copyArrayPart: copyArrayPart, - swapArrayPart: swapArrayPart, - getLocations: getLocations, - context: gl - }; - - function createShader(shaderText, type) { - var shader = gl.createShader(type); - gl.shaderSource(shader, shaderText); - gl.compileShader(shader); - - if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { - var msg = gl.getShaderInfoLog(shader); - window.alert(msg); - throw msg; - } - - return shader; - } - - function createProgram(vertexShaderSrc, fragmentShaderSrc) { - var program = gl.createProgram(); - var vs = createShader(vertexShaderSrc, gl.VERTEX_SHADER); - var fs = createShader(fragmentShaderSrc, gl.FRAGMENT_SHADER); - - gl.attachShader(program, vs); - gl.attachShader(program, fs); - gl.linkProgram(program); - - if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { - var msg = gl.getShaderInfoLog(program); - window.alert(msg); - throw msg; - } - - return program; - } - - function extendArray(buffer, itemsInBuffer, elementsPerItem) { - if ((itemsInBuffer + 1) * elementsPerItem > buffer.length) { - // Every time we run out of space create new array twice bigger. - // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs - var extendedArray = new Float32Array(buffer.length * elementsPerItem * 2); - extendedArray.set(buffer); - - return extendedArray; - } - - return buffer; - } - - function getLocations(program, uniformOrAttributeNames) { - var foundLocations = {}; - for (var i = 0; i < uniformOrAttributeNames.length; ++i) { - var name = uniformOrAttributeNames[i]; - var location = -1; - if (name[0] === 'a' && name[1] === '_') { - location = gl.getAttribLocation(program, name); - if (location === -1) { - throw new Error("Program doesn't have required attribute: " + name); - } - - foundLocations[name.slice(2)] = location; - } else if (name[0] === 'u' && name[1] === '_') { - location = gl.getUniformLocation(program, name); - if (location === null) { - throw new Error("Program doesn't have required uniform: " + name); - } - - foundLocations[name.slice(2)] = location; - } else { - throw new Error("Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'"); - } - } - - return foundLocations; - } -} - -function copyArrayPart(array, to, from, elementsCount) { - for (var i = 0; i < elementsCount; ++i) { - array[to + i] = array[from + i]; - } -} - -function swapArrayPart(array, from, to, elementsCount) { - for (var i = 0; i < elementsCount; ++i) { - var tmp = array[from + i]; - array[from + i] = array[to + i]; - array[to + i] = tmp; - } -} +/** + * @fileOverview Utility functions for webgl rendering. + * + * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + */ + +module.exports = webgl; + +function webgl(gl) { + + return { + createProgram: createProgram, + extendArray: extendArray, + copyArrayPart: copyArrayPart, + swapArrayPart: swapArrayPart, + getLocations: getLocations, + context: gl + }; + + function createShader(shaderText, type) { + var shader = gl.createShader(type); + gl.shaderSource(shader, shaderText); + gl.compileShader(shader); + + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + var msg = gl.getShaderInfoLog(shader); + window.alert(msg); + throw msg; + } + + return shader; + } + + function createProgram(vertexShaderSrc, fragmentShaderSrc) { + var program = gl.createProgram(); + var vs = createShader(vertexShaderSrc, gl.VERTEX_SHADER); + var fs = createShader(fragmentShaderSrc, gl.FRAGMENT_SHADER); + + gl.attachShader(program, vs); + gl.attachShader(program, fs); + gl.linkProgram(program); + + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { + var msg = gl.getShaderInfoLog(program); + window.alert(msg); + throw msg; + } + + return program; + } + + function extendArray(buffer, itemsInBuffer, elementsPerItem) { + if ((itemsInBuffer + 1) * elementsPerItem > buffer.length) { + // Every time we run out of space create new array twice bigger. + // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs + var extendedArray = new Float32Array(buffer.length * elementsPerItem * 2); + extendedArray.set(buffer); + + return extendedArray; + } + + return buffer; + } + + function getLocations(program, uniformOrAttributeNames) { + var foundLocations = {}; + for (var i = 0; i < uniformOrAttributeNames.length; ++i) { + var name = uniformOrAttributeNames[i]; + var location = -1; + if (name[0] === 'a' && name[1] === '_') { + location = gl.getAttribLocation(program, name); + if (location === -1) { + throw new Error("Program doesn't have required attribute: " + name); + } + + foundLocations[name.slice(2)] = location; + } else if (name[0] === 'u' && name[1] === '_') { + location = gl.getUniformLocation(program, name); + if (location === null) { + throw new Error("Program doesn't have required uniform: " + name); + } + + foundLocations[name.slice(2)] = location; + } else { + throw new Error("Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'"); + } + } + + return foundLocations; + } +} + +function copyArrayPart(array, to, from, elementsCount) { + for (var i = 0; i < elementsCount; ++i) { + array[to + i] = array[from + i]; + } +} + +function swapArrayPart(array, from, to, elementsCount) { + for (var i = 0; i < elementsCount; ++i) { + var tmp = array[from + i]; + array[from + i] = array[to + i]; + array[to + i] = tmp; + } +} },{}],54:[function(require,module,exports){ -var Texture = require('./texture.js'); - -module.exports = webglAtlas; - -/** - * My naive implementation of textures atlas. It allows clients to load - * multiple images into atlas and get canvas representing all of them. - * - * @param tilesPerTexture - indicates how many images can be loaded to one - * texture of the atlas. If number of loaded images exceeds this - * parameter a new canvas will be created. - */ -function webglAtlas(tilesPerTexture) { - var tilesPerRow = Math.sqrt(tilesPerTexture || 1024) << 0, - tileSize = tilesPerRow, - lastLoadedIdx = 1, - loadedImages = {}, - dirtyTimeoutId, - skipedDirty = 0, - textures = [], - trackedUrls = []; - - if (!isPowerOf2(tilesPerTexture)) { - throw "Tiles per texture should be power of two."; - } - - // this is the return object - var api = { - /** - * indicates whether atlas has changed texture in it. If true then - * some of the textures has isDirty flag set as well. - */ - isDirty: false, - - /** - * Clears any signs of atlas changes. - */ - clearDirty: clearDirty, - - /** - * Removes given url from collection of tiles in the atlas. - */ - remove: remove, - - /** - * Gets all textures in the atlas. - */ - getTextures: getTextures, - - /** - * Gets coordinates of the given image in the atlas. Coordinates is an object: - * {offset : int } - where offset is an absolute position of the image in the - * atlas. - * - * Absolute means it can be larger than tilesPerTexture parameter, and in that - * case clients should get next texture in getTextures() collection. - */ - getCoordinates: getCoordinates, - - /** - * Asynchronously Loads the image to the atlas. Cross-domain security - * limitation applies. - */ - load: load - }; - - return api; - - function clearDirty() { - var i; - api.isDirty = false; - for (i = 0; i < textures.length; ++i) { - textures[i].isDirty = false; - } - } - - function remove(imgUrl) { - var coordinates = loadedImages[imgUrl]; - if (!coordinates) { - return false; - } - delete loadedImages[imgUrl]; - lastLoadedIdx -= 1; - - - if (lastLoadedIdx === coordinates.offset) { - return true; // Ignore if it's last image in the whole set. - } - - var tileToRemove = getTileCoordinates(coordinates.offset), - lastTileInSet = getTileCoordinates(lastLoadedIdx); - - copy(lastTileInSet, tileToRemove); - - var replacedOffset = loadedImages[trackedUrls[lastLoadedIdx]]; - replacedOffset.offset = coordinates.offset; - trackedUrls[coordinates.offset] = trackedUrls[lastLoadedIdx]; - - markDirty(); - return true; - } - - function getTextures() { - return textures; // I trust you... - } - - function getCoordinates(imgUrl) { - return loadedImages[imgUrl]; - } - - function load(imgUrl, callback) { - if (loadedImages.hasOwnProperty(imgUrl)) { - callback(loadedImages[imgUrl]); - } else { - var img = new window.Image(), - imgId = lastLoadedIdx; - - lastLoadedIdx += 1; - img.crossOrigin = "anonymous"; - img.onload = function() { - markDirty(); - drawAt(imgId, img, callback); - }; - - img.src = imgUrl; - } - } - - function createTexture() { - var texture = new Texture(tilesPerRow * tileSize); - textures.push(texture); - } - - function drawAt(tileNumber, img, callback) { - var tilePosition = getTileCoordinates(tileNumber), - coordinates = { - offset: tileNumber - }; - - if (tilePosition.textureNumber >= textures.length) { - createTexture(); - } - var currentTexture = textures[tilePosition.textureNumber]; - - currentTexture.ctx.drawImage(img, tilePosition.col * tileSize, tilePosition.row * tileSize, tileSize, tileSize); - trackedUrls[tileNumber] = img.src; - - loadedImages[img.src] = coordinates; - currentTexture.isDirty = true; - - callback(coordinates); - } - - function getTileCoordinates(absolutePosition) { - var textureNumber = (absolutePosition / tilesPerTexture) << 0, - localTileNumber = (absolutePosition % tilesPerTexture), - row = (localTileNumber / tilesPerRow) << 0, - col = (localTileNumber % tilesPerRow); - - return { - textureNumber: textureNumber, - row: row, - col: col - }; - } - - function markDirtyNow() { - api.isDirty = true; - skipedDirty = 0; - dirtyTimeoutId = null; - } - - function markDirty() { - // delay this call, since it results in texture reload - if (dirtyTimeoutId) { - window.clearTimeout(dirtyTimeoutId); - skipedDirty += 1; - dirtyTimeoutId = null; - } - - if (skipedDirty > 10) { - markDirtyNow(); - } else { - dirtyTimeoutId = window.setTimeout(markDirtyNow, 400); - } - } - - function copy(from, to) { - var fromCanvas = textures[from.textureNumber].canvas, - toCtx = textures[to.textureNumber].ctx, - x = to.col * tileSize, - y = to.row * tileSize; - - toCtx.drawImage(fromCanvas, from.col * tileSize, from.row * tileSize, tileSize, tileSize, x, y, tileSize, tileSize); - textures[from.textureNumber].isDirty = true; - textures[to.textureNumber].isDirty = true; - } -} - -function isPowerOf2(n) { - return (n & (n - 1)) === 0; -} +var Texture = require('./texture.js'); + +module.exports = webglAtlas; + +/** + * My naive implementation of textures atlas. It allows clients to load + * multiple images into atlas and get canvas representing all of them. + * + * @param tilesPerTexture - indicates how many images can be loaded to one + * texture of the atlas. If number of loaded images exceeds this + * parameter a new canvas will be created. + */ +function webglAtlas(tilesPerTexture) { + var tilesPerRow = Math.sqrt(tilesPerTexture || 1024) << 0, + tileSize = tilesPerRow, + lastLoadedIdx = 1, + loadedImages = {}, + dirtyTimeoutId, + skipedDirty = 0, + textures = [], + trackedUrls = []; + + if (!isPowerOf2(tilesPerTexture)) { + throw "Tiles per texture should be power of two."; + } + + // this is the return object + var api = { + /** + * indicates whether atlas has changed texture in it. If true then + * some of the textures has isDirty flag set as well. + */ + isDirty: false, + + /** + * Clears any signs of atlas changes. + */ + clearDirty: clearDirty, + + /** + * Removes given url from collection of tiles in the atlas. + */ + remove: remove, + + /** + * Gets all textures in the atlas. + */ + getTextures: getTextures, + + /** + * Gets coordinates of the given image in the atlas. Coordinates is an object: + * {offset : int } - where offset is an absolute position of the image in the + * atlas. + * + * Absolute means it can be larger than tilesPerTexture parameter, and in that + * case clients should get next texture in getTextures() collection. + */ + getCoordinates: getCoordinates, + + /** + * Asynchronously Loads the image to the atlas. Cross-domain security + * limitation applies. + */ + load: load + }; + + return api; + + function clearDirty() { + var i; + api.isDirty = false; + for (i = 0; i < textures.length; ++i) { + textures[i].isDirty = false; + } + } + + function remove(imgUrl) { + var coordinates = loadedImages[imgUrl]; + if (!coordinates) { + return false; + } + delete loadedImages[imgUrl]; + lastLoadedIdx -= 1; + + + if (lastLoadedIdx === coordinates.offset) { + return true; // Ignore if it's last image in the whole set. + } + + var tileToRemove = getTileCoordinates(coordinates.offset), + lastTileInSet = getTileCoordinates(lastLoadedIdx); + + copy(lastTileInSet, tileToRemove); + + var replacedOffset = loadedImages[trackedUrls[lastLoadedIdx]]; + replacedOffset.offset = coordinates.offset; + trackedUrls[coordinates.offset] = trackedUrls[lastLoadedIdx]; + + markDirty(); + return true; + } + + function getTextures() { + return textures; // I trust you... + } + + function getCoordinates(imgUrl) { + return loadedImages[imgUrl]; + } + + function load(imgUrl, callback) { + if (loadedImages.hasOwnProperty(imgUrl)) { + callback(loadedImages[imgUrl]); + } else { + var img = new window.Image(), + imgId = lastLoadedIdx; + + lastLoadedIdx += 1; + img.crossOrigin = "anonymous"; + img.onload = function() { + markDirty(); + drawAt(imgId, img, callback); + }; + + img.src = imgUrl; + } + } + + function createTexture() { + var texture = new Texture(tilesPerRow * tileSize); + textures.push(texture); + } + + function drawAt(tileNumber, img, callback) { + var tilePosition = getTileCoordinates(tileNumber), + coordinates = { + offset: tileNumber + }; + + if (tilePosition.textureNumber >= textures.length) { + createTexture(); + } + var currentTexture = textures[tilePosition.textureNumber]; + + currentTexture.ctx.drawImage(img, tilePosition.col * tileSize, tilePosition.row * tileSize, tileSize, tileSize); + trackedUrls[tileNumber] = img.src; + + loadedImages[img.src] = coordinates; + currentTexture.isDirty = true; + + callback(coordinates); + } + + function getTileCoordinates(absolutePosition) { + var textureNumber = (absolutePosition / tilesPerTexture) << 0, + localTileNumber = (absolutePosition % tilesPerTexture), + row = (localTileNumber / tilesPerRow) << 0, + col = (localTileNumber % tilesPerRow); + + return { + textureNumber: textureNumber, + row: row, + col: col + }; + } + + function markDirtyNow() { + api.isDirty = true; + skipedDirty = 0; + dirtyTimeoutId = null; + } + + function markDirty() { + // delay this call, since it results in texture reload + if (dirtyTimeoutId) { + window.clearTimeout(dirtyTimeoutId); + skipedDirty += 1; + dirtyTimeoutId = null; + } + + if (skipedDirty > 10) { + markDirtyNow(); + } else { + dirtyTimeoutId = window.setTimeout(markDirtyNow, 400); + } + } + + function copy(from, to) { + var fromCanvas = textures[from.textureNumber].canvas, + toCtx = textures[to.textureNumber].ctx, + x = to.col * tileSize, + y = to.row * tileSize; + + toCtx.drawImage(fromCanvas, from.col * tileSize, from.row * tileSize, tileSize, tileSize, x, y, tileSize, tileSize); + textures[from.textureNumber].isDirty = true; + textures[to.textureNumber].isDirty = true; + } +} + +function isPowerOf2(n) { + return (n & (n - 1)) === 0; +} },{"./texture.js":52}],55:[function(require,module,exports){ -module.exports = webglImage; - -/** - * Represents a model for image. - */ -function webglImage(size, src) { - return { - /** - * Gets texture index where current image is placed. - */ - _texture : 0, - - /** - * Gets offset in the texture where current image is placed. - */ - _offset : 0, - - /** - * Gets size of the square with the image. - */ - size : typeof size === 'number' ? size : 32, - - /** - * Source of the image. If image is coming not from your domain - * certain origin restrictions applies. - * See http://www.khronos.org/registry/webgl/specs/latest/#4.2 for more details. - */ - src : src - }; -} +module.exports = webglImage; + +/** + * Represents a model for image. + */ +function webglImage(size, src) { + return { + /** + * Gets texture index where current image is placed. + */ + _texture : 0, + + /** + * Gets offset in the texture where current image is placed. + */ + _offset : 0, + + /** + * Gets size of the square with the image. + */ + size : typeof size === 'number' ? size : 32, + + /** + * Source of the image. If image is coming not from your domain + * certain origin restrictions applies. + * See http://www.khronos.org/registry/webgl/specs/latest/#4.2 for more details. + */ + src : src + }; +} },{}],56:[function(require,module,exports){ -/** - * @fileOverview Defines an image nodes for webglGraphics class. - * Shape of nodes is square. - * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com - */ - -var WebglAtlas = require('./webglAtlas.js'); -var glUtils = require('./webgl.js'); - -module.exports = webglImageNodeProgram; - -/** - * Defines simple UI for nodes in webgl renderer. Each node is rendered as an image. - */ -function webglImageNodeProgram() { - // WebGL is gian state machine, we store some properties of the state here: - var ATTRIBUTES_PER_PRIMITIVE = 18; - var nodesFS = createNodeFragmentShader(); - var nodesVS = createNodeVertexShader(); - var tilesPerTexture = 1024; // TODO: Get based on max texture size - var atlas; - var program; - var gl; - var buffer; - var utils; - var locations; - var nodesCount = 0; - var nodes = new Float32Array(64); - var width; - var height; - var transform; - var sizeDirty; - - - return { - load: load, - - /** - * Updates position of current node in the buffer of nodes. - * - * @param idx - index of current node. - * @param pos - new position of the node. - */ - position: position, - - createNode: createNode, - - removeNode: removeNode, - - replaceProperties: replaceProperties, - - updateTransform: updateTransform, - - updateSize: updateSize, - - render: render - }; - - function refreshTexture(texture, idx) { - if (texture.nativeObject) { - gl.deleteTexture(texture.nativeObject); - } - - var nativeObject = gl.createTexture(); - gl.activeTexture(gl["TEXTURE" + idx]); - gl.bindTexture(gl.TEXTURE_2D, nativeObject); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.canvas); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST); - - gl.generateMipmap(gl.TEXTURE_2D); - gl.uniform1i(locations["sampler" + idx], idx); - - texture.nativeObject = nativeObject; - } - - function ensureAtlasTextureUpdated() { - if (atlas.isDirty) { - var textures = atlas.getTextures(), - i; - for (i = 0; i < textures.length; ++i) { - if (textures[i].isDirty || !textures[i].nativeObject) { - refreshTexture(textures[i], i); - } - } - - atlas.clearDirty(); - } - } - - function load(glContext) { - gl = glContext; - utils = glUtils(glContext); - - atlas = new WebglAtlas(tilesPerTexture); - - program = utils.createProgram(nodesVS, nodesFS); - gl.useProgram(program); - locations = utils.getLocations(program, ["a_vertexPos", "a_customAttributes", "u_screenSize", "u_transform", "u_sampler0", "u_sampler1", "u_sampler2", "u_sampler3", "u_tilesPerTexture"]); - - gl.uniform1f(locations.tilesPerTexture, tilesPerTexture); - - gl.enableVertexAttribArray(locations.vertexPos); - gl.enableVertexAttribArray(locations.customAttributes); - - buffer = gl.createBuffer(); - } - - function position(nodeUI, pos) { - var idx = nodeUI.id * ATTRIBUTES_PER_PRIMITIVE; - nodes[idx] = pos.x - nodeUI.size; - nodes[idx + 1] = pos.y - nodeUI.size; - nodes[idx + 2] = nodeUI._offset * 4; - - nodes[idx + 3] = pos.x + nodeUI.size; - nodes[idx + 4] = pos.y - nodeUI.size; - nodes[idx + 5] = nodeUI._offset * 4 + 1; - - nodes[idx + 6] = pos.x - nodeUI.size; - nodes[idx + 7] = pos.y + nodeUI.size; - nodes[idx + 8] = nodeUI._offset * 4 + 2; - - nodes[idx + 9] = pos.x - nodeUI.size; - nodes[idx + 10] = pos.y + nodeUI.size; - nodes[idx + 11] = nodeUI._offset * 4 + 2; - - nodes[idx + 12] = pos.x + nodeUI.size; - nodes[idx + 13] = pos.y - nodeUI.size; - nodes[idx + 14] = nodeUI._offset * 4 + 1; - - nodes[idx + 15] = pos.x + nodeUI.size; - nodes[idx + 16] = pos.y + nodeUI.size; - nodes[idx + 17] = nodeUI._offset * 4 + 3; - } - - function createNode(ui) { - nodes = utils.extendArray(nodes, nodesCount, ATTRIBUTES_PER_PRIMITIVE); - nodesCount += 1; - - var coordinates = atlas.getCoordinates(ui.src); - if (coordinates) { - ui._offset = coordinates.offset; - } else { - ui._offset = 0; - // Image is not yet loaded into the atlas. Reload it: - atlas.load(ui.src, function(coordinates) { - ui._offset = coordinates.offset; - }); - } - } - - function removeNode(nodeUI) { - if (nodesCount > 0) { - nodesCount -= 1; - } - - if (nodeUI.id < nodesCount && nodesCount > 0) { - if (nodeUI.src) { - atlas.remove(nodeUI.src); - } - - utils.copyArrayPart(nodes, nodeUI.id * ATTRIBUTES_PER_PRIMITIVE, nodesCount * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); - } - } - - function replaceProperties(replacedNode, newNode) { - newNode._offset = replacedNode._offset; - } - - function updateTransform(newTransform) { - sizeDirty = true; - transform = newTransform; - } - - function updateSize(w, h) { - width = w; - height = h; - sizeDirty = true; - } - - function render() { - gl.useProgram(program); - gl.bindBuffer(gl.ARRAY_BUFFER, buffer); - gl.bufferData(gl.ARRAY_BUFFER, nodes, gl.DYNAMIC_DRAW); - - if (sizeDirty) { - sizeDirty = false; - gl.uniformMatrix4fv(locations.transform, false, transform); - gl.uniform2f(locations.screenSize, width, height); - } - - gl.vertexAttribPointer(locations.vertexPos, 2, gl.FLOAT, false, 3 * Float32Array.BYTES_PER_ELEMENT, 0); - gl.vertexAttribPointer(locations.customAttributes, 1, gl.FLOAT, false, 3 * Float32Array.BYTES_PER_ELEMENT, 2 * 4); - - ensureAtlasTextureUpdated(); - - gl.drawArrays(gl.TRIANGLES, 0, nodesCount * 6); - } -} - -// TODO: Use glslify for shaders -function createNodeFragmentShader() { - return [ - "precision mediump float;", - "varying vec4 color;", - "varying vec3 vTextureCoord;", - "uniform sampler2D u_sampler0;", - "uniform sampler2D u_sampler1;", - "uniform sampler2D u_sampler2;", - "uniform sampler2D u_sampler3;", - - "void main(void) {", - " if (vTextureCoord.z == 0.) {", - " gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);", - " } else if (vTextureCoord.z == 1.) {", - " gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);", - " } else if (vTextureCoord.z == 2.) {", - " gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);", - " } else if (vTextureCoord.z == 3.) {", - " gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);", - " } else { gl_FragColor = vec4(0, 1, 0, 1); }", - "}" - ].join("\n"); -} - -function createNodeVertexShader() { - return [ - "attribute vec2 a_vertexPos;", - - "attribute float a_customAttributes;", - "uniform vec2 u_screenSize;", - "uniform mat4 u_transform;", - "uniform float u_tilesPerTexture;", - "varying vec3 vTextureCoord;", - - "void main(void) {", - " gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);", - "float corner = mod(a_customAttributes, 4.);", - "float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);", - "float tilesPerRow = sqrt(u_tilesPerTexture);", - "float tileSize = 1./tilesPerRow;", - "float tileColumn = mod(tileIndex, tilesPerRow);", - "float tileRow = floor(tileIndex/tilesPerRow);", - - "if(corner == 0.0) {", - " vTextureCoord.xy = vec2(0, 1);", - "} else if(corner == 1.0) {", - " vTextureCoord.xy = vec2(1, 1);", - "} else if(corner == 2.0) {", - " vTextureCoord.xy = vec2(0, 0);", - "} else {", - " vTextureCoord.xy = vec2(1, 0);", - "}", - - "vTextureCoord *= tileSize;", - "vTextureCoord.x += tileColumn * tileSize;", - "vTextureCoord.y += tileRow * tileSize;", - "vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);", - "}" - ].join("\n"); -} +/** + * @fileOverview Defines an image nodes for webglGraphics class. + * Shape of nodes is square. + * + * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + */ + +var WebglAtlas = require('./webglAtlas.js'); +var glUtils = require('./webgl.js'); + +module.exports = webglImageNodeProgram; + +/** + * Defines simple UI for nodes in webgl renderer. Each node is rendered as an image. + */ +function webglImageNodeProgram() { + // WebGL is gian state machine, we store some properties of the state here: + var ATTRIBUTES_PER_PRIMITIVE = 18; + var nodesFS = createNodeFragmentShader(); + var nodesVS = createNodeVertexShader(); + var tilesPerTexture = 1024; // TODO: Get based on max texture size + var atlas; + var program; + var gl; + var buffer; + var utils; + var locations; + var nodesCount = 0; + var nodes = new Float32Array(64); + var width; + var height; + var transform; + var sizeDirty; + + + return { + load: load, + + /** + * Updates position of current node in the buffer of nodes. + * + * @param idx - index of current node. + * @param pos - new position of the node. + */ + position: position, + + createNode: createNode, + + removeNode: removeNode, + + replaceProperties: replaceProperties, + + updateTransform: updateTransform, + + updateSize: updateSize, + + render: render + }; + + function refreshTexture(texture, idx) { + if (texture.nativeObject) { + gl.deleteTexture(texture.nativeObject); + } + + var nativeObject = gl.createTexture(); + gl.activeTexture(gl["TEXTURE" + idx]); + gl.bindTexture(gl.TEXTURE_2D, nativeObject); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.canvas); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST); + + gl.generateMipmap(gl.TEXTURE_2D); + gl.uniform1i(locations["sampler" + idx], idx); + + texture.nativeObject = nativeObject; + } + + function ensureAtlasTextureUpdated() { + if (atlas.isDirty) { + var textures = atlas.getTextures(), + i; + for (i = 0; i < textures.length; ++i) { + if (textures[i].isDirty || !textures[i].nativeObject) { + refreshTexture(textures[i], i); + } + } + + atlas.clearDirty(); + } + } + + function load(glContext) { + gl = glContext; + utils = glUtils(glContext); + + atlas = new WebglAtlas(tilesPerTexture); + + program = utils.createProgram(nodesVS, nodesFS); + gl.useProgram(program); + locations = utils.getLocations(program, ["a_vertexPos", "a_customAttributes", "u_screenSize", "u_transform", "u_sampler0", "u_sampler1", "u_sampler2", "u_sampler3", "u_tilesPerTexture"]); + + gl.uniform1f(locations.tilesPerTexture, tilesPerTexture); + + gl.enableVertexAttribArray(locations.vertexPos); + gl.enableVertexAttribArray(locations.customAttributes); + + buffer = gl.createBuffer(); + } + + function position(nodeUI, pos) { + var idx = nodeUI.id * ATTRIBUTES_PER_PRIMITIVE; + nodes[idx] = pos.x - nodeUI.size; + nodes[idx + 1] = pos.y - nodeUI.size; + nodes[idx + 2] = nodeUI._offset * 4; + + nodes[idx + 3] = pos.x + nodeUI.size; + nodes[idx + 4] = pos.y - nodeUI.size; + nodes[idx + 5] = nodeUI._offset * 4 + 1; + + nodes[idx + 6] = pos.x - nodeUI.size; + nodes[idx + 7] = pos.y + nodeUI.size; + nodes[idx + 8] = nodeUI._offset * 4 + 2; + + nodes[idx + 9] = pos.x - nodeUI.size; + nodes[idx + 10] = pos.y + nodeUI.size; + nodes[idx + 11] = nodeUI._offset * 4 + 2; + + nodes[idx + 12] = pos.x + nodeUI.size; + nodes[idx + 13] = pos.y - nodeUI.size; + nodes[idx + 14] = nodeUI._offset * 4 + 1; + + nodes[idx + 15] = pos.x + nodeUI.size; + nodes[idx + 16] = pos.y + nodeUI.size; + nodes[idx + 17] = nodeUI._offset * 4 + 3; + } + + function createNode(ui) { + nodes = utils.extendArray(nodes, nodesCount, ATTRIBUTES_PER_PRIMITIVE); + nodesCount += 1; + + var coordinates = atlas.getCoordinates(ui.src); + if (coordinates) { + ui._offset = coordinates.offset; + } else { + ui._offset = 0; + // Image is not yet loaded into the atlas. Reload it: + atlas.load(ui.src, function(coordinates) { + ui._offset = coordinates.offset; + }); + } + } + + function removeNode(nodeUI) { + if (nodesCount > 0) { + nodesCount -= 1; + } + + if (nodeUI.id < nodesCount && nodesCount > 0) { + if (nodeUI.src) { + atlas.remove(nodeUI.src); + } + + utils.copyArrayPart(nodes, nodeUI.id * ATTRIBUTES_PER_PRIMITIVE, nodesCount * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); + } + } + + function replaceProperties(replacedNode, newNode) { + newNode._offset = replacedNode._offset; + } + + function updateTransform(newTransform) { + sizeDirty = true; + transform = newTransform; + } + + function updateSize(w, h) { + width = w; + height = h; + sizeDirty = true; + } + + function render() { + gl.useProgram(program); + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData(gl.ARRAY_BUFFER, nodes, gl.DYNAMIC_DRAW); + + if (sizeDirty) { + sizeDirty = false; + gl.uniformMatrix4fv(locations.transform, false, transform); + gl.uniform2f(locations.screenSize, width, height); + } + + gl.vertexAttribPointer(locations.vertexPos, 2, gl.FLOAT, false, 3 * Float32Array.BYTES_PER_ELEMENT, 0); + gl.vertexAttribPointer(locations.customAttributes, 1, gl.FLOAT, false, 3 * Float32Array.BYTES_PER_ELEMENT, 2 * 4); + + ensureAtlasTextureUpdated(); + + gl.drawArrays(gl.TRIANGLES, 0, nodesCount * 6); + } +} + +// TODO: Use glslify for shaders +function createNodeFragmentShader() { + return [ + "precision mediump float;", + "varying vec4 color;", + "varying vec3 vTextureCoord;", + "uniform sampler2D u_sampler0;", + "uniform sampler2D u_sampler1;", + "uniform sampler2D u_sampler2;", + "uniform sampler2D u_sampler3;", + + "void main(void) {", + " if (vTextureCoord.z == 0.) {", + " gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);", + " } else if (vTextureCoord.z == 1.) {", + " gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);", + " } else if (vTextureCoord.z == 2.) {", + " gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);", + " } else if (vTextureCoord.z == 3.) {", + " gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);", + " } else { gl_FragColor = vec4(0, 1, 0, 1); }", + "}" + ].join("\n"); +} + +function createNodeVertexShader() { + return [ + "attribute vec2 a_vertexPos;", + + "attribute float a_customAttributes;", + "uniform vec2 u_screenSize;", + "uniform mat4 u_transform;", + "uniform float u_tilesPerTexture;", + "varying vec3 vTextureCoord;", + + "void main(void) {", + " gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);", + "float corner = mod(a_customAttributes, 4.);", + "float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);", + "float tilesPerRow = sqrt(u_tilesPerTexture);", + "float tileSize = 1./tilesPerRow;", + "float tileColumn = mod(tileIndex, tilesPerRow);", + "float tileRow = floor(tileIndex/tilesPerRow);", + + "if(corner == 0.0) {", + " vTextureCoord.xy = vec2(0, 1);", + "} else if(corner == 1.0) {", + " vTextureCoord.xy = vec2(1, 1);", + "} else if(corner == 2.0) {", + " vTextureCoord.xy = vec2(0, 0);", + "} else {", + " vTextureCoord.xy = vec2(1, 0);", + "}", + + "vTextureCoord *= tileSize;", + "vTextureCoord.x += tileColumn * tileSize;", + "vTextureCoord.y += tileRow * tileSize;", + "vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);", + "}" + ].join("\n"); +} },{"./webgl.js":53,"./webglAtlas.js":54}],57:[function(require,module,exports){ -var documentEvents = require('../Utils/documentEvents.js'); - -module.exports = webglInputEvents; - -/** - * Monitors graph-related mouse input in webgl graphics and notifies subscribers. - * - * @param {Viva.Graph.View.webglGraphics} webglGraphics - */ -function webglInputEvents(webglGraphics) { - if (webglGraphics.webglInputEvents) { - // Don't listen twice, if we are already attached to this graphics: - return webglGraphics.webglInputEvents; - } - - var mouseCapturedNode = null, - mouseEnterCallback = [], - mouseLeaveCallback = [], - mouseDownCallback = [], - mouseUpCallback = [], - mouseMoveCallback = [], - clickCallback = [], - dblClickCallback = [], - prevSelectStart, - boundRect; - - var root = webglGraphics.getGraphicsRoot(); - startListen(root); - - var api = { - mouseEnter: mouseEnter, - mouseLeave: mouseLeave, - mouseDown: mouseDown, - mouseUp: mouseUp, - mouseMove: mouseMove, - click: click, - dblClick: dblClick, - mouseCapture: mouseCapture, - releaseMouseCapture: releaseMouseCapture - }; - - // TODO I don't remember why this is needed: - webglGraphics.webglInputEvents = api; - - return api; - - function releaseMouseCapture() { - mouseCapturedNode = null; - } - - function mouseCapture(node) { - mouseCapturedNode = node; - } - - function dblClick(callback) { - if (typeof callback === 'function') { - dblClickCallback.push(callback); - } - return api; - } - - function click(callback) { - if (typeof callback === 'function') { - clickCallback.push(callback); - } - return api; - } - - function mouseMove(callback) { - if (typeof callback === 'function') { - mouseMoveCallback.push(callback); - } - return api; - } - - function mouseUp(callback) { - if (typeof callback === 'function') { - mouseUpCallback.push(callback); - } - return api; - } - - function mouseDown(callback) { - if (typeof callback === 'function') { - mouseDownCallback.push(callback); - } - return api; - } - - function mouseLeave(callback) { - if (typeof callback === 'function') { - mouseLeaveCallback.push(callback); - } - return api; - } - - function mouseEnter(callback) { - if (typeof callback === 'function') { - mouseEnterCallback.push(callback); - } - return api; - } - - function preciseCheck(nodeUI, x, y) { - if (nodeUI && nodeUI.size) { - var pos = nodeUI.position, - half = nodeUI.size; - - return pos.x - half < x && x < pos.x + half && - pos.y - half < y && y < pos.y + half; - } - - return true; - } - - function getNodeAtClientPos(pos) { - return webglGraphics.getNodeAtClientPos(pos, preciseCheck); - } - - function stopPropagation(e) { - if (e.stopPropagation) { - e.stopPropagation(); - } else { - e.cancelBubble = true; - } - } - - function handleDisabledEvent(e) { - stopPropagation(e); - return false; - } - - function invoke(callbacksChain, args) { - var i, stopPropagation; - for (i = 0; i < callbacksChain.length; i += 1) { - stopPropagation = callbacksChain[i].apply(undefined, args); - if (stopPropagation) { - return true; - } - } - } - - function startListen(root) { - var pos = { - x: 0, - y: 0 - }, - lastFound = null, - lastUpdate = 1, - lastClickTime = +new Date(), - - handleMouseMove = function(e) { - invoke(mouseMoveCallback, [lastFound, e]); - pos.x = e.clientX; - pos.y = e.clientY; - }, - - handleMouseUp = function() { - documentEvents.off('mousemove', handleMouseMove); - documentEvents.off('mouseup', handleMouseUp); - }, - - updateBoundRect = function() { - boundRect = root.getBoundingClientRect(); - }; - - window.addEventListener('resize', updateBoundRect); - updateBoundRect(); - - // mouse move inside container serves only to track mouse enter/leave events. - root.addEventListener('mousemove', - function(e) { - if (mouseCapturedNode) { - return; - } - if (lastUpdate++ % 7 === 0) { - // since there is no bullet proof method to detect resize - // event, we preemptively update the bounding rectangle - updateBoundRect(); - lastUpdate = 1; - } - var cancelBubble = false, - node; - - pos.x = e.clientX - boundRect.left; - pos.y = e.clientY - boundRect.top; - - node = getNodeAtClientPos(pos); - - if (node && lastFound !== node) { - lastFound = node; - cancelBubble = cancelBubble || invoke(mouseEnterCallback, [lastFound]); - } else if (node === null && lastFound !== node) { - cancelBubble = cancelBubble || invoke(mouseLeaveCallback, [lastFound]); - lastFound = null; - } - - if (cancelBubble) { - stopPropagation(e); - } - }); - - root.addEventListener('mousedown', - function(e) { - var cancelBubble = false, - args; - updateBoundRect(); - pos.x = e.clientX - boundRect.left; - pos.y = e.clientY - boundRect.top; - - args = [getNodeAtClientPos(pos), e]; - if (args[0]) { - cancelBubble = invoke(mouseDownCallback, args); - // we clicked on a node. Following drag should be handled on document events: - documentEvents.on('mousemove', handleMouseMove); - documentEvents.on('mouseup', handleMouseUp); - - prevSelectStart = window.document.onselectstart; - - window.document.onselectstart = handleDisabledEvent; - - lastFound = args[0]; - } else { - lastFound = null; - } - if (cancelBubble) { - stopPropagation(e); - } - }); - - root.addEventListener('mouseup', - function(e) { - var clickTime = +new Date(), - args; - - pos.x = e.clientX - boundRect.left; - pos.y = e.clientY - boundRect.top; - - var nodeAtClientPos = getNodeAtClientPos(pos); - var sameNode = nodeAtClientPos === lastFound; - args = [nodeAtClientPos || lastFound, e]; - if (args[0]) { - window.document.onselectstart = prevSelectStart; - - if (clickTime - lastClickTime < 400 && sameNode) { - invoke(dblClickCallback, args); - } else { - invoke(clickCallback, args); - } - lastClickTime = clickTime; - - if (invoke(mouseUpCallback, args)) { - stopPropagation(e); - } - } - }); - } -} +var documentEvents = require('../Utils/documentEvents.js'); + +module.exports = webglInputEvents; + +/** + * Monitors graph-related mouse input in webgl graphics and notifies subscribers. + * + * @param {Viva.Graph.View.webglGraphics} webglGraphics + */ +function webglInputEvents(webglGraphics) { + if (webglGraphics.webglInputEvents) { + // Don't listen twice, if we are already attached to this graphics: + return webglGraphics.webglInputEvents; + } + + var mouseCapturedNode = null, + mouseEnterCallback = [], + mouseLeaveCallback = [], + mouseDownCallback = [], + mouseUpCallback = [], + mouseMoveCallback = [], + clickCallback = [], + dblClickCallback = [], + prevSelectStart, + boundRect; + + var root = webglGraphics.getGraphicsRoot(); + startListen(root); + + var api = { + mouseEnter: mouseEnter, + mouseLeave: mouseLeave, + mouseDown: mouseDown, + mouseUp: mouseUp, + mouseMove: mouseMove, + click: click, + dblClick: dblClick, + mouseCapture: mouseCapture, + releaseMouseCapture: releaseMouseCapture + }; + + // TODO I don't remember why this is needed: + webglGraphics.webglInputEvents = api; + + return api; + + function releaseMouseCapture() { + mouseCapturedNode = null; + } + + function mouseCapture(node) { + mouseCapturedNode = node; + } + + function dblClick(callback) { + if (typeof callback === 'function') { + dblClickCallback.push(callback); + } + return api; + } + + function click(callback) { + if (typeof callback === 'function') { + clickCallback.push(callback); + } + return api; + } + + function mouseMove(callback) { + if (typeof callback === 'function') { + mouseMoveCallback.push(callback); + } + return api; + } + + function mouseUp(callback) { + if (typeof callback === 'function') { + mouseUpCallback.push(callback); + } + return api; + } + + function mouseDown(callback) { + if (typeof callback === 'function') { + mouseDownCallback.push(callback); + } + return api; + } + + function mouseLeave(callback) { + if (typeof callback === 'function') { + mouseLeaveCallback.push(callback); + } + return api; + } + + function mouseEnter(callback) { + if (typeof callback === 'function') { + mouseEnterCallback.push(callback); + } + return api; + } + + function preciseCheck(nodeUI, x, y) { + if (nodeUI && nodeUI.size) { + var pos = nodeUI.position, + half = nodeUI.size; + + return pos.x - half < x && x < pos.x + half && + pos.y - half < y && y < pos.y + half; + } + + return true; + } + + function getNodeAtClientPos(pos) { + return webglGraphics.getNodeAtClientPos(pos, preciseCheck); + } + + function stopPropagation(e) { + if (e.stopPropagation) { + e.stopPropagation(); + } else { + e.cancelBubble = true; + } + } + + function handleDisabledEvent(e) { + stopPropagation(e); + return false; + } + + function invoke(callbacksChain, args) { + var i, stopPropagation; + for (i = 0; i < callbacksChain.length; i += 1) { + stopPropagation = callbacksChain[i].apply(undefined, args); + if (stopPropagation) { + return true; + } + } + } + + function startListen(root) { + var pos = { + x: 0, + y: 0 + }, + lastFound = null, + lastUpdate = 1, + lastClickTime = +new Date(), + + handleMouseMove = function(e) { + invoke(mouseMoveCallback, [lastFound, e]); + pos.x = e.clientX; + pos.y = e.clientY; + }, + + handleMouseUp = function() { + documentEvents.off('mousemove', handleMouseMove); + documentEvents.off('mouseup', handleMouseUp); + }, + + updateBoundRect = function() { + boundRect = root.getBoundingClientRect(); + }; + + window.addEventListener('resize', updateBoundRect); + updateBoundRect(); + + // mouse move inside container serves only to track mouse enter/leave events. + root.addEventListener('mousemove', + function(e) { + if (mouseCapturedNode) { + return; + } + if (lastUpdate++ % 7 === 0) { + // since there is no bullet proof method to detect resize + // event, we preemptively update the bounding rectangle + updateBoundRect(); + lastUpdate = 1; + } + var cancelBubble = false, + node; + + pos.x = e.clientX - boundRect.left; + pos.y = e.clientY - boundRect.top; + + node = getNodeAtClientPos(pos); + + if (node && lastFound !== node) { + lastFound = node; + cancelBubble = cancelBubble || invoke(mouseEnterCallback, [lastFound]); + } else if (node === null && lastFound !== node) { + cancelBubble = cancelBubble || invoke(mouseLeaveCallback, [lastFound]); + lastFound = null; + } + + if (cancelBubble) { + stopPropagation(e); + } + }); + + root.addEventListener('mousedown', + function(e) { + var cancelBubble = false, + args; + updateBoundRect(); + pos.x = e.clientX - boundRect.left; + pos.y = e.clientY - boundRect.top; + + args = [getNodeAtClientPos(pos), e]; + if (args[0]) { + cancelBubble = invoke(mouseDownCallback, args); + // we clicked on a node. Following drag should be handled on document events: + documentEvents.on('mousemove', handleMouseMove); + documentEvents.on('mouseup', handleMouseUp); + + prevSelectStart = window.document.onselectstart; + + window.document.onselectstart = handleDisabledEvent; + + lastFound = args[0]; + } else { + lastFound = null; + } + if (cancelBubble) { + stopPropagation(e); + } + }); + + root.addEventListener('mouseup', + function(e) { + var clickTime = +new Date(), + args; + + pos.x = e.clientX - boundRect.left; + pos.y = e.clientY - boundRect.top; + + var nodeAtClientPos = getNodeAtClientPos(pos); + var sameNode = nodeAtClientPos === lastFound; + args = [nodeAtClientPos || lastFound, e]; + if (args[0]) { + window.document.onselectstart = prevSelectStart; + + if (clickTime - lastClickTime < 400 && sameNode) { + invoke(dblClickCallback, args); + } else { + invoke(clickCallback, args); + } + lastClickTime = clickTime; + + if (invoke(mouseUpCallback, args)) { + stopPropagation(e); + } + } + }); + } +} },{"../Utils/documentEvents.js":40}],58:[function(require,module,exports){ -var parseColor = require('./parseColor.js'); - -module.exports = webglLine; - -/** - * Defines a webgl line. This class has no rendering logic at all, - * it's just passed to corresponding shader and the shader should - * figure out how to render it. - * - */ -function webglLine(color) { - return { - /** - * Gets or sets color of the line. If you set this property externally - * make sure it always come as integer of 0xRRGGBBAA format - */ - color: parseColor(color) - }; -} +var parseColor = require('./parseColor.js'); + +module.exports = webglLine; + +/** + * Defines a webgl line. This class has no rendering logic at all, + * it's just passed to corresponding shader and the shader should + * figure out how to render it. + * + */ +function webglLine(color) { + return { + /** + * Gets or sets color of the line. If you set this property externally + * make sure it always come as integer of 0xRRGGBBAA format + */ + color: parseColor(color) + }; +} },{"./parseColor.js":51}],59:[function(require,module,exports){ -/** - * @fileOverview Defines a naive form of links for webglGraphics class. - * This form allows to change color of links. - **/ - -var glUtils = require('./webgl.js'); - -module.exports = webglLinkProgram; - -/** - * Defines UI for links in webgl renderer. - */ -function webglLinkProgram() { - var ATTRIBUTES_PER_PRIMITIVE = 6, // primitive is Line with two points. Each has x,y and color = 3 * 2 attributes. - BYTES_PER_LINK = 2 * (2 * Float32Array.BYTES_PER_ELEMENT + Uint32Array.BYTES_PER_ELEMENT), // two nodes * (x, y + color) - linksFS = [ - 'precision mediump float;', - 'varying vec4 color;', - 'void main(void) {', - ' gl_FragColor = color;', - '}' - ].join('\n'), - - linksVS = [ - 'attribute vec2 a_vertexPos;', - 'attribute vec4 a_color;', - - 'uniform vec2 u_screenSize;', - 'uniform mat4 u_transform;', - - 'varying vec4 color;', - - 'void main(void) {', - ' gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);', - ' color = a_color.abgr;', - '}' - ].join('\n'), - - program, - gl, - buffer, - utils, - locations, - linksCount = 0, - frontLinkId, // used to track z-index of links. - storage = new ArrayBuffer(16 * BYTES_PER_LINK), - positions = new Float32Array(storage), - colors = new Uint32Array(storage), - width, - height, - transform, - sizeDirty, - - ensureEnoughStorage = function () { - // TODO: this is a duplicate of webglNodeProgram code. Extract it to webgl.js - if ((linksCount+1)*BYTES_PER_LINK > storage.byteLength) { - // Every time we run out of space create new array twice bigger. - // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs - var extendedStorage = new ArrayBuffer(storage.byteLength * 2), - extendedPositions = new Float32Array(extendedStorage), - extendedColors = new Uint32Array(extendedStorage); - - extendedColors.set(colors); // should be enough to copy just one view. - positions = extendedPositions; - colors = extendedColors; - storage = extendedStorage; - } - }; - - return { - load : function (glContext) { - gl = glContext; - utils = glUtils(glContext); - - program = utils.createProgram(linksVS, linksFS); - gl.useProgram(program); - locations = utils.getLocations(program, ['a_vertexPos', 'a_color', 'u_screenSize', 'u_transform']); - - gl.enableVertexAttribArray(locations.vertexPos); - gl.enableVertexAttribArray(locations.color); - - buffer = gl.createBuffer(); - }, - - position: function (linkUi, fromPos, toPos) { - var linkIdx = linkUi.id, - offset = linkIdx * ATTRIBUTES_PER_PRIMITIVE; - positions[offset] = fromPos.x; - positions[offset + 1] = fromPos.y; - colors[offset + 2] = linkUi.color; - - positions[offset + 3] = toPos.x; - positions[offset + 4] = toPos.y; - colors[offset + 5] = linkUi.color; - }, - - createLink : function (ui) { - ensureEnoughStorage(); - - linksCount += 1; - frontLinkId = ui.id; - }, - - removeLink : function (ui) { - if (linksCount > 0) { linksCount -= 1; } - // swap removed link with the last link. This will give us O(1) performance for links removal: - if (ui.id < linksCount && linksCount > 0) { - // using colors as a view to array buffer is okay here. - utils.copyArrayPart(colors, ui.id * ATTRIBUTES_PER_PRIMITIVE, linksCount * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); - } - }, - - updateTransform : function (newTransform) { - sizeDirty = true; - transform = newTransform; - }, - - updateSize : function (w, h) { - width = w; - height = h; - sizeDirty = true; - }, - - render : function () { - gl.useProgram(program); - gl.bindBuffer(gl.ARRAY_BUFFER, buffer); - gl.bufferData(gl.ARRAY_BUFFER, storage, gl.DYNAMIC_DRAW); - - if (sizeDirty) { - sizeDirty = false; - gl.uniformMatrix4fv(locations.transform, false, transform); - gl.uniform2f(locations.screenSize, width, height); - } - - gl.vertexAttribPointer(locations.vertexPos, 2, gl.FLOAT, false, 3 * Float32Array.BYTES_PER_ELEMENT, 0); - gl.vertexAttribPointer(locations.color, 4, gl.UNSIGNED_BYTE, true, 3 * Float32Array.BYTES_PER_ELEMENT, 2 * 4); - - gl.drawArrays(gl.LINES, 0, linksCount * 2); - - frontLinkId = linksCount - 1; - }, - - bringToFront : function (link) { - if (frontLinkId > link.id) { - utils.swapArrayPart(positions, link.id * ATTRIBUTES_PER_PRIMITIVE, frontLinkId * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); - } - if (frontLinkId > 0) { - frontLinkId -= 1; - } - }, - - getFrontLinkId : function () { - return frontLinkId; - } - }; -} +/** + * @fileOverview Defines a naive form of links for webglGraphics class. + * This form allows to change color of links. + **/ + +var glUtils = require('./webgl.js'); + +module.exports = webglLinkProgram; + +/** + * Defines UI for links in webgl renderer. + */ +function webglLinkProgram() { + var ATTRIBUTES_PER_PRIMITIVE = 6, // primitive is Line with two points. Each has x,y and color = 3 * 2 attributes. + BYTES_PER_LINK = 2 * (2 * Float32Array.BYTES_PER_ELEMENT + Uint32Array.BYTES_PER_ELEMENT), // two nodes * (x, y + color) + linksFS = [ + 'precision mediump float;', + 'varying vec4 color;', + 'void main(void) {', + ' gl_FragColor = color;', + '}' + ].join('\n'), + + linksVS = [ + 'attribute vec2 a_vertexPos;', + 'attribute vec4 a_color;', + + 'uniform vec2 u_screenSize;', + 'uniform mat4 u_transform;', + + 'varying vec4 color;', + + 'void main(void) {', + ' gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);', + ' color = a_color.abgr;', + '}' + ].join('\n'), + + program, + gl, + buffer, + utils, + locations, + linksCount = 0, + frontLinkId, // used to track z-index of links. + storage = new ArrayBuffer(16 * BYTES_PER_LINK), + positions = new Float32Array(storage), + colors = new Uint32Array(storage), + width, + height, + transform, + sizeDirty, + + ensureEnoughStorage = function () { + // TODO: this is a duplicate of webglNodeProgram code. Extract it to webgl.js + if ((linksCount+1)*BYTES_PER_LINK > storage.byteLength) { + // Every time we run out of space create new array twice bigger. + // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs + var extendedStorage = new ArrayBuffer(storage.byteLength * 2), + extendedPositions = new Float32Array(extendedStorage), + extendedColors = new Uint32Array(extendedStorage); + + extendedColors.set(colors); // should be enough to copy just one view. + positions = extendedPositions; + colors = extendedColors; + storage = extendedStorage; + } + }; + + return { + load : function (glContext) { + gl = glContext; + utils = glUtils(glContext); + + program = utils.createProgram(linksVS, linksFS); + gl.useProgram(program); + locations = utils.getLocations(program, ['a_vertexPos', 'a_color', 'u_screenSize', 'u_transform']); + + gl.enableVertexAttribArray(locations.vertexPos); + gl.enableVertexAttribArray(locations.color); + + buffer = gl.createBuffer(); + }, + + position: function (linkUi, fromPos, toPos) { + var linkIdx = linkUi.id, + offset = linkIdx * ATTRIBUTES_PER_PRIMITIVE; + positions[offset] = fromPos.x; + positions[offset + 1] = fromPos.y; + colors[offset + 2] = linkUi.color; + + positions[offset + 3] = toPos.x; + positions[offset + 4] = toPos.y; + colors[offset + 5] = linkUi.color; + }, + + createLink : function (ui) { + ensureEnoughStorage(); + + linksCount += 1; + frontLinkId = ui.id; + }, + + removeLink : function (ui) { + if (linksCount > 0) { linksCount -= 1; } + // swap removed link with the last link. This will give us O(1) performance for links removal: + if (ui.id < linksCount && linksCount > 0) { + // using colors as a view to array buffer is okay here. + utils.copyArrayPart(colors, ui.id * ATTRIBUTES_PER_PRIMITIVE, linksCount * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); + } + }, + + updateTransform : function (newTransform) { + sizeDirty = true; + transform = newTransform; + }, + + updateSize : function (w, h) { + width = w; + height = h; + sizeDirty = true; + }, + + render : function () { + gl.useProgram(program); + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData(gl.ARRAY_BUFFER, storage, gl.DYNAMIC_DRAW); + + if (sizeDirty) { + sizeDirty = false; + gl.uniformMatrix4fv(locations.transform, false, transform); + gl.uniform2f(locations.screenSize, width, height); + } + + gl.vertexAttribPointer(locations.vertexPos, 2, gl.FLOAT, false, 3 * Float32Array.BYTES_PER_ELEMENT, 0); + gl.vertexAttribPointer(locations.color, 4, gl.UNSIGNED_BYTE, true, 3 * Float32Array.BYTES_PER_ELEMENT, 2 * 4); + + gl.drawArrays(gl.LINES, 0, linksCount * 2); + + frontLinkId = linksCount - 1; + }, + + bringToFront : function (link) { + if (frontLinkId > link.id) { + utils.swapArrayPart(positions, link.id * ATTRIBUTES_PER_PRIMITIVE, frontLinkId * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); + } + if (frontLinkId > 0) { + frontLinkId -= 1; + } + }, + + getFrontLinkId : function () { + return frontLinkId; + } + }; +} },{"./webgl.js":53}],60:[function(require,module,exports){ -/** - * @fileOverview Defines a naive form of nodes for webglGraphics class. - * This form allows to change color of node. Shape of nodes is rectangular. - * - * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka - */ - -var glUtils = require('./webgl.js'); - -module.exports = webglNodeProgram; - -/** - * Defines simple UI for nodes in webgl renderer. Each node is rendered as square. Color and size can be changed. - */ -function webglNodeProgram() { - var ATTRIBUTES_PER_PRIMITIVE = 4; // Primitive is point, x, y, size, color - // x, y, z - floats, color = uint. - var BYTES_PER_NODE = 3 * Float32Array.BYTES_PER_ELEMENT + Uint32Array.BYTES_PER_ELEMENT; - var nodesFS = [ - 'precision mediump float;', - 'varying vec4 color;', - - 'void main(void) {', - ' gl_FragColor = color;', - '}' - ].join('\n'); - var nodesVS = [ - 'attribute vec3 a_vertexPos;', - 'attribute vec4 a_color;', - 'uniform vec2 u_screenSize;', - 'uniform mat4 u_transform;', - 'varying vec4 color;', - - 'void main(void) {', - ' gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);', - ' gl_PointSize = a_vertexPos.z * u_transform[0][0];', - ' color = a_color.abgr;', - '}' - ].join('\n'); - - var program; - var gl; - var buffer; - var locations; - var utils; - var storage = new ArrayBuffer(16 * BYTES_PER_NODE); - var positions = new Float32Array(storage); - var colors = new Uint32Array(storage); - var nodesCount = 0; - var width; - var height; - var transform; - var sizeDirty; - - return { - load: load, - - /** - * Updates position of node in the buffer of nodes. - * - * @param idx - index of current node. - * @param pos - new position of the node. - */ - position: position, - - updateTransform: updateTransform, - - updateSize: updateSize, - - removeNode: removeNode, - - createNode: createNode, - - replaceProperties: replaceProperties, - - render: render - }; - - function ensureEnoughStorage() { - if ((nodesCount + 1) * BYTES_PER_NODE >= storage.byteLength) { - // Every time we run out of space create new array twice bigger. - // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs - var extendedStorage = new ArrayBuffer(storage.byteLength * 2), - extendedPositions = new Float32Array(extendedStorage), - extendedColors = new Uint32Array(extendedStorage); - - extendedColors.set(colors); // should be enough to copy just one view. - positions = extendedPositions; - colors = extendedColors; - storage = extendedStorage; - } - } - - function load(glContext) { - gl = glContext; - utils = glUtils(glContext); - - program = utils.createProgram(nodesVS, nodesFS); - gl.useProgram(program); - locations = utils.getLocations(program, ['a_vertexPos', 'a_color', 'u_screenSize', 'u_transform']); - - gl.enableVertexAttribArray(locations.vertexPos); - gl.enableVertexAttribArray(locations.color); - - buffer = gl.createBuffer(); - } - - function position(nodeUI, pos) { - var idx = nodeUI.id; - - positions[idx * ATTRIBUTES_PER_PRIMITIVE] = pos.x; - positions[idx * ATTRIBUTES_PER_PRIMITIVE + 1] = -pos.y; - positions[idx * ATTRIBUTES_PER_PRIMITIVE + 2] = nodeUI.size; - - colors[idx * ATTRIBUTES_PER_PRIMITIVE + 3] = nodeUI.color; - } - - function updateTransform(newTransform) { - sizeDirty = true; - transform = newTransform; - } - - function updateSize(w, h) { - width = w; - height = h; - sizeDirty = true; - } - - function removeNode(node) { - if (nodesCount > 0) { - nodesCount -= 1; - } - - if (node.id < nodesCount && nodesCount > 0) { - // we can use colors as a 'view' into array array buffer. - utils.copyArrayPart(colors, node.id * ATTRIBUTES_PER_PRIMITIVE, nodesCount * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); - } - } - - function createNode() { - ensureEnoughStorage(); - nodesCount += 1; - } - - function replaceProperties(/* replacedNode, newNode */) {} - - function render() { - gl.useProgram(program); - gl.bindBuffer(gl.ARRAY_BUFFER, buffer); - gl.bufferData(gl.ARRAY_BUFFER, storage, gl.DYNAMIC_DRAW); - - if (sizeDirty) { - sizeDirty = false; - gl.uniformMatrix4fv(locations.transform, false, transform); - gl.uniform2f(locations.screenSize, width, height); - } - - gl.vertexAttribPointer(locations.vertexPos, 3, gl.FLOAT, false, ATTRIBUTES_PER_PRIMITIVE * Float32Array.BYTES_PER_ELEMENT, 0); - gl.vertexAttribPointer(locations.color, 4, gl.UNSIGNED_BYTE, true, ATTRIBUTES_PER_PRIMITIVE * Float32Array.BYTES_PER_ELEMENT, 3 * 4); - - gl.drawArrays(gl.POINTS, 0, nodesCount); - } -} +/** + * @fileOverview Defines a naive form of nodes for webglGraphics class. + * This form allows to change color of node. Shape of nodes is rectangular. + * + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka + */ + +var glUtils = require('./webgl.js'); + +module.exports = webglNodeProgram; + +/** + * Defines simple UI for nodes in webgl renderer. Each node is rendered as square. Color and size can be changed. + */ +function webglNodeProgram() { + var ATTRIBUTES_PER_PRIMITIVE = 4; // Primitive is point, x, y, size, color + // x, y, z - floats, color = uint. + var BYTES_PER_NODE = 3 * Float32Array.BYTES_PER_ELEMENT + Uint32Array.BYTES_PER_ELEMENT; + var nodesFS = [ + 'precision mediump float;', + 'varying vec4 color;', + + 'void main(void) {', + ' gl_FragColor = color;', + '}' + ].join('\n'); + var nodesVS = [ + 'attribute vec3 a_vertexPos;', + 'attribute vec4 a_color;', + 'uniform vec2 u_screenSize;', + 'uniform mat4 u_transform;', + 'varying vec4 color;', + + 'void main(void) {', + ' gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);', + ' gl_PointSize = a_vertexPos.z * u_transform[0][0];', + ' color = a_color.abgr;', + '}' + ].join('\n'); + + var program; + var gl; + var buffer; + var locations; + var utils; + var storage = new ArrayBuffer(16 * BYTES_PER_NODE); + var positions = new Float32Array(storage); + var colors = new Uint32Array(storage); + var nodesCount = 0; + var width; + var height; + var transform; + var sizeDirty; + + return { + load: load, + + /** + * Updates position of node in the buffer of nodes. + * + * @param idx - index of current node. + * @param pos - new position of the node. + */ + position: position, + + updateTransform: updateTransform, + + updateSize: updateSize, + + removeNode: removeNode, + + createNode: createNode, + + replaceProperties: replaceProperties, + + render: render + }; + + function ensureEnoughStorage() { + if ((nodesCount + 1) * BYTES_PER_NODE >= storage.byteLength) { + // Every time we run out of space create new array twice bigger. + // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs + var extendedStorage = new ArrayBuffer(storage.byteLength * 2), + extendedPositions = new Float32Array(extendedStorage), + extendedColors = new Uint32Array(extendedStorage); + + extendedColors.set(colors); // should be enough to copy just one view. + positions = extendedPositions; + colors = extendedColors; + storage = extendedStorage; + } + } + + function load(glContext) { + gl = glContext; + utils = glUtils(glContext); + + program = utils.createProgram(nodesVS, nodesFS); + gl.useProgram(program); + locations = utils.getLocations(program, ['a_vertexPos', 'a_color', 'u_screenSize', 'u_transform']); + + gl.enableVertexAttribArray(locations.vertexPos); + gl.enableVertexAttribArray(locations.color); + + buffer = gl.createBuffer(); + } + + function position(nodeUI, pos) { + var idx = nodeUI.id; + + positions[idx * ATTRIBUTES_PER_PRIMITIVE] = pos.x; + positions[idx * ATTRIBUTES_PER_PRIMITIVE + 1] = -pos.y; + positions[idx * ATTRIBUTES_PER_PRIMITIVE + 2] = nodeUI.size; + + colors[idx * ATTRIBUTES_PER_PRIMITIVE + 3] = nodeUI.color; + } + + function updateTransform(newTransform) { + sizeDirty = true; + transform = newTransform; + } + + function updateSize(w, h) { + width = w; + height = h; + sizeDirty = true; + } + + function removeNode(node) { + if (nodesCount > 0) { + nodesCount -= 1; + } + + if (node.id < nodesCount && nodesCount > 0) { + // we can use colors as a 'view' into array array buffer. + utils.copyArrayPart(colors, node.id * ATTRIBUTES_PER_PRIMITIVE, nodesCount * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); + } + } + + function createNode() { + ensureEnoughStorage(); + nodesCount += 1; + } + + function replaceProperties(/* replacedNode, newNode */) {} + + function render() { + gl.useProgram(program); + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData(gl.ARRAY_BUFFER, storage, gl.DYNAMIC_DRAW); + + if (sizeDirty) { + sizeDirty = false; + gl.uniformMatrix4fv(locations.transform, false, transform); + gl.uniform2f(locations.screenSize, width, height); + } + + gl.vertexAttribPointer(locations.vertexPos, 3, gl.FLOAT, false, ATTRIBUTES_PER_PRIMITIVE * Float32Array.BYTES_PER_ELEMENT, 0); + gl.vertexAttribPointer(locations.color, 4, gl.UNSIGNED_BYTE, true, ATTRIBUTES_PER_PRIMITIVE * Float32Array.BYTES_PER_ELEMENT, 3 * 4); + + gl.drawArrays(gl.POINTS, 0, nodesCount); + } +} },{"./webgl.js":53}],61:[function(require,module,exports){ -var parseColor = require('./parseColor.js'); - -module.exports = webglSquare; - -/** - * Can be used as a callback in the webglGraphics.node() function, to - * create a custom looking node. - * - * @param size - size of the node in pixels. - * @param color - color of the node in '#rrggbbaa' or '#rgb' format. - */ -function webglSquare(size, color) { - return { - /** - * Gets or sets size of the square side. - */ - size: typeof size === 'number' ? size : 10, - - /** - * Gets or sets color of the square. - */ - color: parseColor(color) - }; -} +var parseColor = require('./parseColor.js'); + +module.exports = webglSquare; + +/** + * Can be used as a callback in the webglGraphics.node() function, to + * create a custom looking node. + * + * @param size - size of the node in pixels. + * @param color - color of the node in '#rrggbbaa' or '#rgb' format. + */ +function webglSquare(size, color) { + return { + /** + * Gets or sets size of the square side. + */ + size: typeof size === 'number' ? size : 10, + + /** + * Gets or sets color of the square. + */ + color: parseColor(color) + }; +} },{"./parseColor.js":51}],62:[function(require,module,exports){ -// todo: this should be generated at build time. -module.exports = '0.8.1'; +// todo: this should be generated at build time. +module.exports = '0.8.1'; },{}]},{},[1])(1) }); \ No newline at end of file diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index c84b0b7..bd2b3f4 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=s*d-f*c,0===y?null:(x=y<0?-y/2:y/2,x=0,w=c*p-d*l,b.x=(w<0?w-x:w+x)/y,w=f*l-s*p,b.y=(w<0?w-x:w+x)/y,b)))}n.exports=r},{}],4:[function(e,n,t){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":5,"./src/degree.js":6}],5:[function(e,n,t){function r(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;i0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function f(e,n,t){if(e<1||n<1||t<1)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=p();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;i0&&a.addLink(s,r-1+o*e+u),o>0&&a.addLink(s,r+(o-1)*e+u),i>0&&a.addLink(s,r+o*e+(i-1)*e*n)}return a}function c(e){if(e<0)throw new Error("Invalid number of nodes in balanced tree");var n,t=p(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;n= 0");var n,t=p();for(n=0;n=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,u=e("ngraph.random").random(o||42),s=p();for(i=0;i=0&&t.links.splice(n,1)),r&&(n=o(e,r.links),n>=0&&r.links.splice(n,1)),U(e,"remove"),F(),!0}function h(e,n){var t,r=f(e);if(!r)return null;for(t=0;t0&&(O.fire("changed",M),M.length=0)}function P(){return Object.keys?k:j}function k(e){if("function"==typeof e)for(var n=Object.keys(A),t=0;t=0?i:-1,o);return v.push(a),a},getTotalMovement:function(){return x},removeSpring:function(e){if(e){var n=v.indexOf(e);return n>-1?(v.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return h.getBestNewPosition(e)},getBBox:function(){return h.box},gravity:function(e){return void 0!==e?(n.gravity=e,g.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,g.options({theta:e}),this):n.theta}};return o(n,w),a(w),w}n.exports=r},{"./lib/bounds":16,"./lib/createBody":17,"./lib/dragForce":18,"./lib/eulerIntegrator":19,"./lib/spring":20,"./lib/springForce":21,"ngraph.events":7,"ngraph.expose":8,"ngraph.merge":13,"ngraph.quadtreebh":22}],16:[function(e,n,t){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;u1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/u}n.exports=r},{}],20:[function(e,n,t){function r(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=r},{}],21:[function(e,n,t){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":8,"ngraph.merge":13,"ngraph.random":26}],22:[function(e,n,t){function r(e,n){return 0===n?e.quad0:1===n?e.quad1:2===n?e.quad2:3===n?e.quad3:null}function o(e,n,t){0===n?e.quad0=t:1===n?e.quad1=t:2===n?e.quad2=t:3===n&&(e.quad3=t)}n.exports=function(n){function t(){var e=h[m];return e?(e.quad0=null,e.quad1=null,e.quad2=null,e.quad3=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0):(e=new f,h[m]=e),++m,e}function i(e){var n,t,r,o,i=p,a=0,u=0,f=1,c=0,d=1;for(i[0]=y;f;){var v=i[c],h=v.body;f-=1,c+=1;var m=h!==e;h&&m?(t=h.pos.x-e.pos.x,r=h.pos.y-e.pos.y,o=Math.sqrt(t*t+r*r),0===o&&(t=(s.nextDouble()-.5)/50,r=(s.nextDouble()-.5)/50,o=Math.sqrt(t*t+r*r)),n=l*h.mass*e.mass/(o*o*o),a+=n*t,u+=n*r):m&&(t=v.massX/v.mass-e.pos.x,r=v.massY/v.mass-e.pos.y,o=Math.sqrt(t*t+r*r),0===o&&(t=(s.nextDouble()-.5)/50,r=(s.nextDouble()-.5)/50,o=Math.sqrt(t*t+r*r)),(v.right-v.left)/oi&&(i=f),ca&&(a=c)}var d=i-r,l=a-o;for(d>l?a=o+d:i=r+l,m=0,y=t(),y.left=r,y.right=i,y.top=o,y.bottom=a,n=s-1,n>=0&&(y.body=e[n]);n--;)u(e[n],y)}function u(e){for(v.reset(),v.push(y,e);!v.isEmpty();){var n=v.pop(),i=n.node,a=n.body;if(i.body){var u=i.body;if(i.body=null,d(u.pos,a.pos)){var f=3;do{var c=s.nextDouble(),l=(i.right-i.left)*c,p=(i.bottom-i.top)*c;u.pos.x=i.left+l,u.pos.y=i.top+p,f-=1}while(f>0&&d(u.pos,a.pos));if(0===f&&d(u.pos,a.pos))return}v.push(i,u),v.push(i,a)}else{var g=a.pos.x,h=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*g,i.massY=i.massY+a.mass*h;var m=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;g>w&&(m+=1,x=w,w=i.right),h>E&&(m+=2,b=E,E=i.bottom);var L=r(i,m);L?v.push(L,a):(L=t(),L.left=x,L.top=b,L.right=w,L.bottom=E,L.body=a,o(i,m,L))}}}n=n||{},n.gravity="number"==typeof n.gravity?n.gravity:-1,n.theta="number"==typeof n.theta?n.theta:.8;var s=e("ngraph.random").random(1984),f=e("./node"),c=e("./insertStack"),d=e("./isSamePosition"),l=n.gravity,p=[],v=new c,g=n.theta,h=[],m=0,y=t();return{insertBodies:a,getRoot:function(){return y},updateBodyForce:i,options:function(e){return e?("number"==typeof e.gravity&&(l=e.gravity),"number"==typeof e.theta&&(g=e.theta),this):{gravity:l,theta:g}}}}},{"./insertStack":23,"./isSamePosition":24,"./node":25,"ngraph.random":26}],23:[function(e,n,t){function r(){this.stack=[],this.popIdx=0}function o(e,n){this.node=e,this.body=n}n.exports=r,r.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new o(e,n),++this.popIdx},pop:function(){if(this.popIdx>0)return this.stack[--this.popIdx]},reset:function(){this.popIdx=0}}},{}],24:[function(e,n,t){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return t<1e-8&&r<1e-8}},{}],25:[function(e,n,t){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],26:[function(e,n,t){function r(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function o(e,n){var t=n||r();if("function"!=typeof t.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var r,o,i;for(r=e.length-1;r>0;--r)o=t.next(r+1),i=e[o],e[o]=e[r],e[r]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,r,o;for(n=e.length-1;n>0;--n)r=t.next(n+1),o=e[r],e[r]=e[n],e[n]=o;return e}}}n.exports={random:r,randomIterator:o}},{}],27:[function(e,n,t){function r(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=r},{}],28:[function(e,n,t){function r(e,n){var t=o(e);if(void 0===n)return t;for(var r=Object.keys(n),i=0;iv&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},j=function(e){p=!1,o.off("touchmove",k),o.off("touchend",j),o.off("touchcancel",j),c=null,r&&r(e)},A=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,o.on("touchmove",k),o.on("touchend",j),o.on("touchcancel",j))},_=function(e){return 1===e.touches.length?A(e,e.touches[0]):void(2===e.touches.length&&(m(e), -y(e),v=P(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),o.off("mousemove",w),o.off("mouseup",E),o.off("touchmove",k),o.off("touchend",j),o.off("touchcancel",j),N(null)}}}n.exports=r;var o=e("../Utils/documentEvents.js"),i=e("../Utils/browserInfo.js"),a=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":39,"../Utils/documentEvents.js":40,"../Utils/findElementPosition.js":41}],36:[function(e,n,t){function r(e,n){var t=o(n),r=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){r=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(r);var o=i[e.id];return o&&o.onStart&&o.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(r),r=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(r){var t=i[r.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=r;var o=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":57}],37:[function(e,n,t){function r(e,n){function t(e){return d[e]}n=o(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var r=i(n.seed),u=new a(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(e){return{x:r.next(n.maxX),y:r.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"!=typeof z||z}function r(){G=G||window.document.body,F=F||i(e,{springLength:80,springCoeff:2e-4}),O=O||a(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||s)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=f(function(){return p()},M)):(X=0,V=0,R=f(p,M)))}function g(){J||(W=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;e0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):r=e),t},getSvgRoot:function(){return t}};return i(b),b}n.exports=r;var o=e("simplesvg"),i=e("ngraph.events"),a=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":34,"ngraph.events":7,simplesvg:28}],50:[function(e,n,t){function r(e){e=c(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,r,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=i(),N=a(),P=function(e){return u()},k=function(e){return s(3014898687)},j=function(){L.updateTransform(y),N.updateTransform(y)},A=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),r&&r.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),N&&N.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){if("function"==typeof e)return P=e,this},link:function(e){if("function"==typeof e)return k=e,this},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:o,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&N.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,j()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=P(e);return r.id=t,r.position=n,r.node=e,N.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],j()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,j(),I(this),y[0]},resetScale:function(){return A(),r&&(_(),j()),this},init:function(o){var i={};if(e.preserveDrawingBuffer&&(i.preserveDrawingBuffer=!0),n=o,_(),A(),n.appendChild(t),r=t.getContext("experimental-webgl",i),!r){var a="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(a),a}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var u=e.clearColorValue;r.clearColor(u.r,u.g,u.b,u.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}L.load(r),L.updateSize(d/2,l/2),N.load(r),N.updateSize(d/2,l/2),j(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(t0&&(h-=1);var n=b[e.id];delete b[e.id],N.removeNode(n);var t=n.id;if(te.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;o=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!o(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:r,getCoordinates:a,load:u};return E}function o(e){return 0===(e&e-1)}var i=e("./texture.js");n.exports=r},{"./texture.js":52}],55:[function(e,n,t){function r(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=r},{}],56:[function(e,n,t){function r(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(A-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*N,A*N,N))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*A)}var v,g,h,m,y,x,w,b,E,L,N=18,P=o(),k=i(),j=1024,A=0,_=new Float32Array(64);return{load:t,position:r,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function o(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function i(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var a=e("./webglAtlas.js"),u=e("./webgl.js");n.exports=r},{"./webgl.js":53,"./webglAtlas.js":54}],57:[function(e,n,t){function r(e){function n(){x=null}function t(e){x=e}function r(e){return"function"==typeof e&&k.push(e),A}function i(e){return"function"==typeof e&&P.push(e),A}function a(e){return"function"==typeof e&&N.push(e),A}function u(e){return"function"==typeof e&&L.push(e),A}function s(e){return"function"==typeof e&&E.push(e),A}function f(e){return"function"==typeof e&&b.push(e),A}function c(e){return"function"==typeof e&&w.push(e),A}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oh.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,r=o(a),e=r.createProgram(v,p),n.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&r.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&r.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],60:[function(e,n,t){function r(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(P),N=n,P=t,L=e}}function n(e){d=e,v=o(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;N[t*x]=n.x,N[t*x+1]=-n.y,N[t*x+2]=e.size,P[t*x+3]=e.color}function r(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(P,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),N=new Float32Array(L),P=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:r,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],61:[function(e,n,t){function r(e,n){return{size:"number"==typeof e?e:10,color:o(n)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],62:[function(e,n,t){n.exports="0.8.1"},{}]},{},[1])(1)}); \ No newline at end of file +y(e),v=P(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),o.off("mousemove",w),o.off("mouseup",E),o.off("touchmove",k),o.off("touchend",j),o.off("touchcancel",j),N(null)}}}n.exports=r;var o=e("../Utils/documentEvents.js"),i=e("../Utils/browserInfo.js"),a=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":39,"../Utils/documentEvents.js":40,"../Utils/findElementPosition.js":41}],36:[function(e,n,t){function r(e,n){var t=o(n),r=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){r=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(r);var o=i[e.id];return o&&o.onStart&&o.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(r),r=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(r){var t=i[r.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=r;var o=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":57}],37:[function(e,n,t){function r(e,n){function t(e){return d[e]}n=o(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var r=i(n.seed),u=new a(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(e){return{x:r.next(n.maxX),y:r.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"!=typeof z||z}function r(){G=G||window.document.body,F=F||i(e,{springLength:80,springCoeff:2e-4}),O=O||a(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||s)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=f(function(){return p()},M)):(X=0,V=0,R=f(p,M)))}function g(){J||(W=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;e0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):r=e),t},getSvgRoot:function(){return t}};return i(b),b}n.exports=r;var o=e("simplesvg"),i=e("ngraph.events"),a=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":34,"ngraph.events":7,simplesvg:28}],50:[function(e,n,t){function r(e){e=c(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,r,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=i(),N=a(),P=function(e){return u()},k=function(e){return s(3014898687)},j=function(){L.updateTransform(y),N.updateTransform(y)},A=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),r&&r.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),N&&N.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){if("function"==typeof e)return P=e,this},link:function(e){if("function"==typeof e)return k=e,this},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:o,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&N.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,j()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=P(e);return r.id=t,r.position=n,r.node=e,N.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],j()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,j(),I(this),y[0]},resetScale:function(){return A(),r&&(_(),j()),this},updateSize:_,init:function(o){var i={};if(e.preserveDrawingBuffer&&(i.preserveDrawingBuffer=!0),n=o,_(),A(),n.appendChild(t),r=t.getContext("experimental-webgl",i),!r){var a="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(a),a}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var u=e.clearColorValue;r.clearColor(u.r,u.g,u.b,u.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}L.load(r),L.updateSize(d/2,l/2),N.load(r),N.updateSize(d/2,l/2),j(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(t0&&(h-=1);var n=b[e.id];delete b[e.id],N.removeNode(n);var t=n.id;if(te.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;o=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!o(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:r,getCoordinates:a,load:u};return E}function o(e){return 0===(e&e-1)}var i=e("./texture.js");n.exports=r},{"./texture.js":52}],55:[function(e,n,t){function r(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=r},{}],56:[function(e,n,t){function r(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(A-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*N,A*N,N))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*A)}var v,g,h,m,y,x,w,b,E,L,N=18,P=o(),k=i(),j=1024,A=0,_=new Float32Array(64);return{load:t,position:r,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function o(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function i(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var a=e("./webglAtlas.js"),u=e("./webgl.js");n.exports=r},{"./webgl.js":53,"./webglAtlas.js":54}],57:[function(e,n,t){function r(e){function n(){x=null}function t(e){x=e}function r(e){return"function"==typeof e&&k.push(e),A}function i(e){return"function"==typeof e&&P.push(e),A}function a(e){return"function"==typeof e&&N.push(e),A}function u(e){return"function"==typeof e&&L.push(e),A}function s(e){return"function"==typeof e&&E.push(e),A}function f(e){return"function"==typeof e&&b.push(e),A}function c(e){return"function"==typeof e&&w.push(e),A}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oh.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,r=o(a),e=r.createProgram(v,p),n.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&r.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&r.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],60:[function(e,n,t){function r(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(P),N=n,P=t,L=e}}function n(e){d=e,v=o(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;N[t*x]=n.x,N[t*x+1]=-n.y,N[t*x+2]=e.size,P[t*x+3]=e.color}function r(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(P,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),N=new Float32Array(L),P=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:r,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],61:[function(e,n,t){function r(e,n){return{size:"number"==typeof e?e:10,color:o(n)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],62:[function(e,n,t){n.exports="0.8.1"},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..549379a --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3681 @@ +{ + "name": "vivagraphjs", + "version": "0.9.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz", + "integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=", + "dev": true + }, + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "dev": true + }, + "add-event-listener": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/add-event-listener/-/add-event-listener-0.0.1.tgz", + "integrity": "sha1-p2Ip68ZMiu+uIEoWJzovJVq+otA=" + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true + }, + "array-slice": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.0.0.tgz", + "integrity": "sha1-5zA08A3MH0CHYAj9IP6ud71LfC8=", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "asn1.js": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.1.tgz", + "integrity": "sha1-SLokC0WpKA6UdImQull9IWYX/UA=", + "dev": true, + "requires": { + "bn.js": "4.11.7", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "assert": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.3.0.tgz", + "integrity": "sha1-A5OaYiWCqBLMICMgoLmlbJuBWEk=", + "dev": true, + "requires": { + "util": "0.10.3" + } + }, + "astw": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/astw/-/astw-2.2.0.tgz", + "integrity": "sha1-e9QXhNMkk5h66yOba04cV6hzuRc=", + "dev": true, + "requires": { + "acorn": "4.0.13" + } + }, + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "Base64": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/Base64/-/Base64-0.2.1.tgz", + "integrity": "sha1-ujpCMHCOGGcFBl5mur3Uw1z2ACg=", + "dev": true + }, + "base64-js": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", + "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=", + "dev": true + }, + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", + "dev": true + }, + "bl": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", + "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", + "dev": true, + "requires": { + "readable-stream": "1.0.34" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + } + } + }, + "bn.js": { + "version": "4.11.7", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.7.tgz", + "integrity": "sha512-LxFiV5mefv0ley0SzqkOPR1bC4EbpPx8LkOz5vMe/Yi15t5hzwgO/G+tc7wOtL4PZTYjwHu8JnEiSLumuSjSfA==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browser-pack": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-3.2.0.tgz", + "integrity": "sha1-+qHLxBSHsazEdH43PhFIrf/Q4tk=", + "dev": true, + "requires": { + "combine-source-map": "0.3.0", + "concat-stream": "1.4.10", + "defined": "0.0.0", + "JSONStream": "0.8.4", + "through2": "0.5.1", + "umd": "2.1.0" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", + "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "3.0.0" + } + } + } + }, + "browser-resolve": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", + "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=", + "dev": true, + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "browserify": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-8.1.3.tgz", + "integrity": "sha1-8zpUmjpsNoIZsHX9z+bfGV4Empo=", + "dev": true, + "requires": { + "assert": "1.3.0", + "browser-pack": "3.2.0", + "browser-resolve": "1.11.2", + "browserify-zlib": "0.1.4", + "buffer": "3.6.0", + "builtins": "0.0.7", + "commondir": "0.0.1", + "concat-stream": "1.4.10", + "console-browserify": "1.1.0", + "constants-browserify": "0.0.1", + "crypto-browserify": "3.11.1", + "deep-equal": "0.2.2", + "defined": "0.0.0", + "deps-sort": "1.3.9", + "domain-browser": "1.1.7", + "duplexer2": "0.0.2", + "events": "1.0.2", + "glob": "4.5.3", + "http-browserify": "1.7.0", + "https-browserify": "0.0.1", + "inherits": "2.0.3", + "insert-module-globals": "6.6.3", + "isarray": "0.0.1", + "JSONStream": "0.8.4", + "labeled-stream-splicer": "1.0.2", + "module-deps": "3.9.1", + "os-browserify": "0.1.2", + "parents": "1.0.1", + "path-browserify": "0.0.0", + "process": "0.10.1", + "punycode": "1.2.4", + "querystring-es3": "0.2.1", + "readable-stream": "1.1.14", + "resolve": "0.7.4", + "shallow-copy": "0.0.1", + "shasum": "1.0.2", + "shell-quote": "0.0.1", + "stream-browserify": "1.0.0", + "string_decoder": "0.10.31", + "subarg": "1.0.0", + "syntax-error": "1.3.0", + "through2": "1.1.1", + "timers-browserify": "1.4.2", + "tty-browserify": "0.0.0", + "umd": "2.1.0", + "url": "0.10.3", + "util": "0.10.3", + "vm-browserify": "0.0.4", + "xtend": "3.0.0" + } + }, + "browserify-aes": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.0.6.tgz", + "integrity": "sha1-Xncl297x/Vkw1OurSFZ85FHEigo=", + "dev": true, + "requires": { + "buffer-xor": "1.0.3", + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.0", + "inherits": "2.0.3" + } + }, + "browserify-cipher": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", + "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", + "dev": true, + "requires": { + "browserify-aes": "1.0.6", + "browserify-des": "1.0.0", + "evp_bytestokey": "1.0.0" + } + }, + "browserify-des": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", + "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "des.js": "1.0.0", + "inherits": "2.0.3" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "4.11.7", + "randombytes": "2.0.5" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, + "requires": { + "bn.js": "4.11.7", + "browserify-rsa": "4.0.1", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "elliptic": "6.4.0", + "inherits": "2.0.3", + "parse-asn1": "5.1.0" + } + }, + "browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", + "dev": true, + "requires": { + "pako": "0.2.9" + } + }, + "buffer": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz", + "integrity": "sha1-pyyTb3e5a/UvX357RnGAYoVR3vs=", + "dev": true, + "requires": { + "base64-js": "0.0.8", + "ieee754": "1.1.8", + "isarray": "1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "buffer-equal": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.2.tgz", + "integrity": "sha1-7Lt5D1aNQAmKYkK1SAXHWAXrk48=", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtins": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-0.0.7.tgz", + "integrity": "sha1-NVIZzWzxjb58Acx/0tznZc/cVJo=", + "dev": true + }, + "bunker": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/bunker/-/bunker-0.1.2.tgz", + "integrity": "sha1-yImSRkqOKm7ehpMDdfkrWAd++Xw=", + "dev": true, + "requires": { + "burrito": "0.2.12" + } + }, + "burrito": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/burrito/-/burrito-0.2.12.tgz", + "integrity": "sha1-0NbmrIHV6ZeJxvpKzLCwAx6lT2s=", + "dev": true, + "requires": { + "traverse": "0.5.2", + "uglify-js": "1.1.1" + }, + "dependencies": { + "traverse": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.5.2.tgz", + "integrity": "sha1-4gPFjV9/DjfbbnTArLkpuwm2HYU=", + "dev": true + }, + "uglify-js": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-1.1.1.tgz", + "integrity": "sha1-7nGpfEzv0GoamyBDfzQRiYKqA1s=", + "dev": true + } + } + }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "dev": true + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "charm": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/charm/-/charm-0.1.2.tgz", + "integrity": "sha1-BsIe7RobBq62dVPNxT4jJ0usIpY=", + "dev": true + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + } + } + }, + "clone": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", + "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "combine-source-map": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.3.0.tgz", + "integrity": "sha1-2edPWT2c1DgHMSy12EbUUe+qnrc=", + "dev": true, + "requires": { + "convert-source-map": "0.3.5", + "inline-source-map": "0.3.1", + "source-map": "0.1.43" + } + }, + "commondir": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-0.0.1.tgz", + "integrity": "sha1-ifAP3NUbUZxXhzP+xWPmptp/W+I=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.4.10.tgz", + "integrity": "sha1-rMO79WAsuMyYDGrIQPp9hgPj7zY=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "1.1.14", + "typedarray": "0.0.6" + } + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "0.1.4" + } + }, + "constants-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-0.0.1.tgz", + "integrity": "sha1-kld9tSe6bEzwpFaNhLwDH0QeIfI=", + "dev": true + }, + "convert-source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-0.3.5.tgz", + "integrity": "sha1-8dgClQr33SYxof6+BZZVDIarMZA=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "create-ecdh": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", + "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", + "dev": true, + "requires": { + "bn.js": "4.11.7", + "elliptic": "6.4.0" + } + }, + "create-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "sha.js": "2.4.8" + } + }, + "create-hmac": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", + "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.8" + } + }, + "crypto-browserify": { + "version": "3.11.1", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.11.1.tgz", + "integrity": "sha512-Na7ZlwCOqoaW5RwUK1WpXws2kv8mNhWdTlzob0UXulk6G9BDbyiJaGTYBIX61Ozn9l1EPPJpICZb4DaOpT9NlQ==", + "dev": true, + "requires": { + "browserify-cipher": "1.0.0", + "browserify-sign": "4.0.4", + "create-ecdh": "4.0.0", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "diffie-hellman": "5.0.2", + "inherits": "2.0.3", + "pbkdf2": "3.0.13", + "public-encrypt": "4.0.0", + "randombytes": "2.0.5" + } + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "dateformat": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.0.0.tgz", + "integrity": "sha1-J0Pjq7XD/CRi5SfcpEXgTp9N7hc=", + "dev": true + }, + "deap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/deap/-/deap-1.0.0.tgz", + "integrity": "sha1-sUi/gkMKJ2mbdIOgPra2dYW/yIg=", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "deep-equal": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.2.2.tgz", + "integrity": "sha1-hLdFiW80xoTpjyzg5Cq69Du6AX0=", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "1.0.2" + } + }, + "defined": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-0.0.0.tgz", + "integrity": "sha1-817qfXBekzuvE7LwOz+D2SFAOz4=", + "dev": true + }, + "del": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/del/-/del-1.2.1.tgz", + "integrity": "sha1-rtblvNfLcyXfNPVjEl+iZbLBoBQ=", + "dev": true, + "requires": { + "each-async": "1.1.1", + "globby": "2.1.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "object-assign": "3.0.0", + "rimraf": "2.6.1" + } + }, + "deprecated": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", + "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", + "dev": true + }, + "deps-sort": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-1.3.9.tgz", + "integrity": "sha1-Kd//U+F7Nq7K51MK27v2IsLtGnE=", + "dev": true, + "requires": { + "JSONStream": "1.3.1", + "shasum": "1.0.2", + "subarg": "1.0.0", + "through2": "1.1.1" + }, + "dependencies": { + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "JSONStream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.1.tgz", + "integrity": "sha1-cH92HgHa6eFvG8+TcDt4xwlmV5o=", + "dev": true, + "requires": { + "jsonparse": "1.3.1", + "through": "2.3.8" + } + } + } + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "detect-file": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-0.1.0.tgz", + "integrity": "sha1-STXe39lIhkjgBrASlWbpOGcR6mM=", + "dev": true, + "requires": { + "fs-exists-sync": "0.1.0" + } + }, + "detective": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/detective/-/detective-4.5.0.tgz", + "integrity": "sha1-blqMaybmx6JUsca210kNmOyR7dE=", + "dev": true, + "requires": { + "acorn": "4.0.13", + "defined": "1.0.0" + }, + "dependencies": { + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + } + } + }, + "diffie-hellman": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", + "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", + "dev": true, + "requires": { + "bn.js": "4.11.7", + "miller-rabin": "4.0.0", + "randombytes": "2.0.5" + } + }, + "difflet": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/difflet/-/difflet-0.2.6.tgz", + "integrity": "sha1-qyOzH1ZJtvqo49KsvTNEZzZcpvo=", + "dev": true, + "requires": { + "charm": "0.1.2", + "deep-is": "0.1.3", + "traverse": "0.6.6" + } + }, + "domain-browser": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", + "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", + "dev": true + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "requires": { + "readable-stream": "1.1.14" + } + }, + "each-async": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/each-async/-/each-async-1.1.1.tgz", + "integrity": "sha1-3uUim98KtrogEqOV4bhpq/iBNHM=", + "dev": true, + "requires": { + "onetime": "1.1.0", + "set-immediate-shim": "1.0.1" + } + }, + "elliptic": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", + "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", + "dev": true, + "requires": { + "bn.js": "4.11.7", + "brorand": "1.1.0", + "hash.js": "1.1.3", + "hmac-drbg": "1.0.1", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "end-of-stream": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", + "dev": true, + "requires": { + "once": "1.3.3" + }, + "dependencies": { + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + } + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "events": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/events/-/events-1.0.2.tgz", + "integrity": "sha1-dYSdz+k9EPsFfDAFWv29UdBqjiQ=", + "dev": true + }, + "evp_bytestokey": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.0.tgz", + "integrity": "sha1-SXtmrZ/vZc18CKYYCCS6FHa2blM=", + "dev": true, + "requires": { + "create-hash": "1.1.3" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.3" + } + }, + "expand-tilde": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", + "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "fancy-log": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.0.tgz", + "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "time-stamp": "1.1.0" + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "find-index": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", + "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", + "dev": true + }, + "findup-sync": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.4.3.tgz", + "integrity": "sha1-QAQ5Kee8YK3wt/SCfExudaDeyhI=", + "dev": true, + "requires": { + "detect-file": "0.1.0", + "is-glob": "2.0.1", + "micromatch": "2.3.11", + "resolve-dir": "0.1.1" + } + }, + "fined": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", + "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", + "dev": true, + "requires": { + "expand-tilde": "2.0.2", + "is-plain-object": "2.0.4", + "object.defaults": "1.1.0", + "object.pick": "1.2.0", + "parse-filepath": "1.0.1" + }, + "dependencies": { + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "1.0.1" + } + } + } + }, + "first-chunk-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", + "dev": true + }, + "flagged-respawn": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-0.3.2.tgz", + "integrity": "sha1-/xke3c1wiKZ1smEP/8l2vpuAdLU=", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "fs-exists-sync": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", + "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "gaze": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", + "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", + "dev": true, + "requires": { + "globule": "0.1.0" + } + }, + "gintersect": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/gintersect/-/gintersect-0.1.0.tgz", + "integrity": "sha1-moy2qAt9bpVawzUVSVsSEmJ7GBY=" + }, + "glob": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "2.0.10", + "once": "1.4.0" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "glob-stream": { + "version": "3.1.18", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", + "dev": true, + "requires": { + "glob": "4.5.3", + "glob2base": "0.0.12", + "minimatch": "2.0.10", + "ordered-read-streams": "0.1.0", + "through2": "0.6.5", + "unique-stream": "1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "glob-watcher": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", + "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", + "dev": true, + "requires": { + "gaze": "0.5.2" + } + }, + "glob2base": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", + "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", + "dev": true, + "requires": { + "find-index": "0.1.1" + } + }, + "global-modules": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", + "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=", + "dev": true, + "requires": { + "global-prefix": "0.1.5", + "is-windows": "0.2.0" + } + }, + "global-prefix": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", + "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=", + "dev": true, + "requires": { + "homedir-polyfill": "1.0.1", + "ini": "1.3.4", + "is-windows": "0.2.0", + "which": "1.3.0" + } + }, + "globby": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-2.1.0.tgz", + "integrity": "sha1-npGSvNM/Srak+JTl5+qLcTITxII=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "async": "1.5.2", + "glob": "5.0.15", + "object-assign": "3.0.0" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "2.0.10", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + } + } + }, + "globule": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", + "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", + "dev": true, + "requires": { + "glob": "3.1.21", + "lodash": "1.0.2", + "minimatch": "0.2.14" + }, + "dependencies": { + "glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true, + "requires": { + "graceful-fs": "1.2.3", + "inherits": "1.0.2", + "minimatch": "0.2.14" + } + }, + "graceful-fs": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "dev": true + }, + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + } + } + }, + "glogg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz", + "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "dev": true, + "requires": { + "natives": "1.1.0" + } + }, + "gulp": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", + "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", + "dev": true, + "requires": { + "archy": "1.0.0", + "chalk": "1.1.3", + "deprecated": "0.0.1", + "gulp-util": "3.0.8", + "interpret": "1.0.3", + "liftoff": "2.3.0", + "minimist": "1.2.0", + "orchestrator": "0.3.8", + "pretty-hrtime": "1.0.3", + "semver": "4.3.6", + "tildify": "1.2.0", + "v8flags": "2.1.1", + "vinyl-fs": "0.3.14" + } + }, + "gulp-rename": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.2.2.tgz", + "integrity": "sha1-OtRCh2PwXidk3sHGfYaNsnVoeBc=", + "dev": true + }, + "gulp-run": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/gulp-run/-/gulp-run-1.7.1.tgz", + "integrity": "sha1-4XwKy3wwtuKu7iPAREKpbAys7/o=", + "dev": true, + "requires": { + "gulp-util": "3.0.8", + "lodash.defaults": "4.2.0", + "lodash.template": "4.4.0", + "vinyl": "0.4.6" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "lodash.template": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", + "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0", + "lodash.templatesettings": "4.1.0" + } + }, + "lodash.templatesettings": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", + "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "0.2.0", + "clone-stats": "0.0.1" + } + } + } + }, + "gulp-uglify": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-1.5.4.tgz", + "integrity": "sha1-UkeI2HZm0J+dDCH7IXf5ADmmWMk=", + "dev": true, + "requires": { + "deap": "1.0.0", + "fancy-log": "1.3.0", + "gulp-util": "3.0.8", + "isobject": "2.1.0", + "through2": "2.0.3", + "uglify-js": "2.6.4", + "uglify-save-license": "0.4.1", + "vinyl-sourcemaps-apply": "0.2.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", + "dev": true + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.3", + "xtend": "4.0.1" + } + }, + "uglify-js": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.6.4.tgz", + "integrity": "sha1-ZeovswWck5RpLxX+2HwrNsFrmt8=", + "dev": true, + "requires": { + "async": "0.2.10", + "source-map": "0.5.6", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } + } + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "dev": true, + "requires": { + "array-differ": "1.0.0", + "array-uniq": "1.0.3", + "beeper": "1.1.1", + "chalk": "1.1.3", + "dateformat": "2.0.0", + "fancy-log": "1.3.0", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2", + "minimist": "1.2.0", + "multipipe": "0.1.2", + "object-assign": "3.0.0", + "replace-ext": "0.0.1", + "through2": "2.0.3", + "vinyl": "0.5.3" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.3", + "xtend": "4.0.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "1.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "hash-base": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", + "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "1.1.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "homedir-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "dev": true, + "requires": { + "parse-passwd": "1.0.0" + } + }, + "http-browserify": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/http-browserify/-/http-browserify-1.7.0.tgz", + "integrity": "sha1-M3la3nLfiKz7/TZ3PO/tp2RzWyA=", + "dev": true, + "requires": { + "Base64": "0.2.1", + "inherits": "2.0.3" + } + }, + "https-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", + "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=", + "dev": true + }, + "ieee754": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=", + "dev": true + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", + "dev": true + }, + "inline-source-map": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.3.1.tgz", + "integrity": "sha1-pSi1FOaJ/OkNswiehw2S9Sestes=", + "dev": true, + "requires": { + "source-map": "0.3.0" + }, + "dependencies": { + "source-map": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.3.0.tgz", + "integrity": "sha1-hYb7mloAXltQHiHNGLbyG0V60fk=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "insert-module-globals": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-6.6.3.tgz", + "integrity": "sha1-IGOOKaMPntHKLjqCX7wsulJG3fw=", + "dev": true, + "requires": { + "combine-source-map": "0.6.1", + "concat-stream": "1.4.10", + "is-buffer": "1.1.5", + "JSONStream": "1.3.1", + "lexical-scope": "1.2.0", + "process": "0.11.10", + "through2": "1.1.1", + "xtend": "4.0.1" + }, + "dependencies": { + "combine-source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.6.1.tgz", + "integrity": "sha1-m0oJwxYDPXaODxHgKfonMOB5rZY=", + "dev": true, + "requires": { + "convert-source-map": "1.1.3", + "inline-source-map": "0.5.0", + "lodash.memoize": "3.0.4", + "source-map": "0.4.4" + } + }, + "convert-source-map": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", + "dev": true + }, + "inline-source-map": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.5.0.tgz", + "integrity": "sha1-Skxd2OT7Xps82mDIIt+tyu5m4K8=", + "dev": true, + "requires": { + "source-map": "0.4.4" + } + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "JSONStream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.1.tgz", + "integrity": "sha1-cH92HgHa6eFvG8+TcDt4xwlmV5o=", + "dev": true, + "requires": { + "jsonparse": "1.3.1", + "through": "2.3.8" + } + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "interpret": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.3.tgz", + "integrity": "sha1-y8NcYu7uc/Gat7EKgBURQBr8D5A=", + "dev": true + }, + "is-absolute": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.2.6.tgz", + "integrity": "sha1-IN5p89uULvLYe5wto28XIjWxtes=", + "dev": true, + "requires": { + "is-relative": "0.2.1", + "is-windows": "0.2.0" + } + }, + "is-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", + "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", + "dev": true + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "dev": true, + "requires": { + "is-path-inside": "1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", + "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-relative": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz", + "integrity": "sha1-0n9MfVFtF1+2ENuEu+7yPDvJeqU=", + "dev": true, + "requires": { + "is-unc-path": "0.1.2" + } + }, + "is-unc-path": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-0.1.2.tgz", + "integrity": "sha1-arBTpyVzwQJQ/0FqOBTDUXivObk=", + "dev": true, + "requires": { + "unc-path-regex": "0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-windows": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", + "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "json-stable-stringify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", + "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonparse": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz", + "integrity": "sha1-MwVCrT8KZUZlt3jz6y2an6UHrGQ=", + "dev": true + }, + "JSONStream": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.8.4.tgz", + "integrity": "sha1-kWV9/m/4V0gwZhMrRhi2Lo9Ih70=", + "dev": true, + "requires": { + "jsonparse": "0.0.5", + "through": "2.3.8" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + }, + "labeled-stream-splicer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-1.0.2.tgz", + "integrity": "sha1-RhUzFTd4SYHo/SZOHzpDTE4N3WU=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "isarray": "0.0.1", + "stream-splicer": "1.3.2" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + }, + "lexical-scope": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/lexical-scope/-/lexical-scope-1.2.0.tgz", + "integrity": "sha1-/Ope3HBKSzqHls3KQZw6CvryLfQ=", + "dev": true, + "requires": { + "astw": "2.2.0" + } + }, + "liftoff": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.3.0.tgz", + "integrity": "sha1-qY8v9nGD2Lp8+soQVIvX/wVQs4U=", + "dev": true, + "requires": { + "extend": "3.0.1", + "findup-sync": "0.4.3", + "fined": "1.1.0", + "flagged-respawn": "0.3.2", + "lodash.isplainobject": "4.0.6", + "lodash.isstring": "4.0.1", + "lodash.mapvalues": "4.6.0", + "rechoir": "0.6.2", + "resolve": "1.4.0" + }, + "dependencies": { + "resolve": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz", + "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", + "dev": true, + "requires": { + "path-parse": "1.0.5" + } + } + } + }, + "lodash": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", + "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", + "dev": true + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", + "dev": true + }, + "lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", + "dev": true + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", + "dev": true + }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", + "dev": true + }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "dev": true, + "requires": { + "lodash._root": "3.0.1" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", + "dev": true + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "lodash.mapvalues": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", + "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=", + "dev": true + }, + "lodash.memoize": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", + "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=", + "dev": true + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash._basetostring": "3.0.1", + "lodash._basevalues": "3.0.0", + "lodash._isiterateecall": "3.0.9", + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0", + "lodash.keys": "3.1.2", + "lodash.restparam": "3.6.1", + "lodash.templatesettings": "3.1.1" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0" + } + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.3" + } + }, + "miller-rabin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.0.tgz", + "integrity": "sha1-SmL7HUKTPAVYOYL0xxb2+55sbT0=", + "dev": true, + "requires": { + "bn.js": "4.11.7", + "brorand": "1.1.0" + } + }, + "minimalistic-assert": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", + "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "module-deps": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-3.9.1.tgz", + "integrity": "sha1-6nXK+RmQkNJbDVUStaysuW5/h/M=", + "dev": true, + "requires": { + "browser-resolve": "1.11.2", + "concat-stream": "1.4.10", + "defined": "1.0.0", + "detective": "4.5.0", + "duplexer2": "0.0.2", + "inherits": "2.0.3", + "JSONStream": "1.3.1", + "parents": "1.0.1", + "readable-stream": "1.1.14", + "resolve": "1.4.0", + "stream-combiner2": "1.0.2", + "subarg": "1.0.0", + "through2": "1.1.1", + "xtend": "4.0.1" + }, + "dependencies": { + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "JSONStream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.1.tgz", + "integrity": "sha1-cH92HgHa6eFvG8+TcDt4xwlmV5o=", + "dev": true, + "requires": { + "jsonparse": "1.3.1", + "through": "2.3.8" + } + }, + "resolve": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz", + "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", + "dev": true, + "requires": { + "path-parse": "1.0.5" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "dev": true, + "requires": { + "duplexer2": "0.0.2" + } + }, + "natives": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.0.tgz", + "integrity": "sha1-6f+EFBimsux6SV6TmYT3jxY+bjE=", + "dev": true + }, + "ngraph.centrality": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ngraph.centrality/-/ngraph.centrality-0.1.3.tgz", + "integrity": "sha1-bKB7QXmv8AfYSY7e8lZoizfYdp0=" + }, + "ngraph.events": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/ngraph.events/-/ngraph.events-0.0.3.tgz", + "integrity": "sha1-OPVTFvPSB61jH/lPZiLKjywOh9A=" + }, + "ngraph.expose": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/ngraph.expose/-/ngraph.expose-0.0.0.tgz", + "integrity": "sha1-dGw0kDo4SMRdAzsUvGRhnqhf5ao=" + }, + "ngraph.forcelayout": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ngraph.forcelayout/-/ngraph.forcelayout-0.1.2.tgz", + "integrity": "sha1-PC4SJ/KRSLqyn8WLweg3SfYdS8U=", + "requires": { + "ngraph.events": "0.0.3", + "ngraph.physics.simulator": "0.1.1" + } + }, + "ngraph.fromjson": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/ngraph.fromjson/-/ngraph.fromjson-0.1.7.tgz", + "integrity": "sha1-VXEnCsj+ED6xaEQUbolIrUIhnHM=", + "requires": { + "ngraph.graph": "0.0.11" + } + }, + "ngraph.generators": { + "version": "0.0.15", + "resolved": "https://registry.npmjs.org/ngraph.generators/-/ngraph.generators-0.0.15.tgz", + "integrity": "sha1-GgnH6S2IPXi8gWwGwvZkC0X0z/I=", + "requires": { + "ngraph.graph": "0.0.11", + "ngraph.random": "0.0.1" + } + }, + "ngraph.graph": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/ngraph.graph/-/ngraph.graph-0.0.11.tgz", + "integrity": "sha1-nxCnJn71l3Q5rFB7r8un9O1yhAE=", + "requires": { + "ngraph.events": "0.0.3" + } + }, + "ngraph.merge": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/ngraph.merge/-/ngraph.merge-0.0.1.tgz", + "integrity": "sha1-5OgM43WBo8lrF9VF46Q8hUNLkCU=" + }, + "ngraph.physics.primitives": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ngraph.physics.primitives/-/ngraph.physics.primitives-0.0.7.tgz", + "integrity": "sha1-Xcnhebofkubex3SwHNaJFBILeVs=" + }, + "ngraph.physics.simulator": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ngraph.physics.simulator/-/ngraph.physics.simulator-0.1.1.tgz", + "integrity": "sha1-h5RmUATQJbnkIyEV/O/9l7+sCK0=", + "requires": { + "ngraph.events": "0.0.3", + "ngraph.expose": "0.0.0", + "ngraph.merge": "0.0.1", + "ngraph.physics.primitives": "0.0.7", + "ngraph.quadtreebh": "0.0.4", + "ngraph.random": "0.0.1" + } + }, + "ngraph.quadtreebh": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/ngraph.quadtreebh/-/ngraph.quadtreebh-0.0.4.tgz", + "integrity": "sha1-xwDUTm5K8HttBQAbo5h/9eLc1iw=", + "requires": { + "ngraph.random": "0.0.1" + } + }, + "ngraph.random": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/ngraph.random/-/ngraph.random-0.0.1.tgz", + "integrity": "sha1-wAji67/f+vF+0Q5LvJE+VnFmvPg=" + }, + "ngraph.remove-overlaps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ngraph.remove-overlaps/-/ngraph.remove-overlaps-1.0.0.tgz", + "integrity": "sha1-tMBjVT6kzx/3gWjnt//2JhfA2fQ=", + "dev": true + }, + "ngraph.tojson": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ngraph.tojson/-/ngraph.tojson-0.1.3.tgz", + "integrity": "sha1-chUq8zBsABeXu3zJKTDpIbp76zo=" + }, + "nopt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-2.2.1.tgz", + "integrity": "sha1-KqCbfRdoSHs7ianFqlIzW/8Lrqc=", + "dev": true, + "requires": { + "abbrev": "1.1.0" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.0.2" + } + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "1.0.1", + "array-slice": "1.0.0", + "for-own": "1.0.0", + "isobject": "3.0.1" + }, + "dependencies": { + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "object.pick": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.2.0.tgz", + "integrity": "sha1-tTkr7peC2m2ft9avr1OXefEjTCs=", + "dev": true, + "requires": { + "isobject": "2.1.0" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "optimist": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=", + "dev": true, + "requires": { + "wordwrap": "0.0.3" + } + }, + "orchestrator": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", + "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", + "dev": true, + "requires": { + "end-of-stream": "0.1.5", + "sequencify": "0.0.7", + "stream-consume": "0.1.0" + } + }, + "ordered-read-streams": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", + "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", + "dev": true + }, + "os-browserify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.1.2.tgz", + "integrity": "sha1-ScoCk+CxlZCl9d4Qx/JlphfY/lQ=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", + "dev": true + }, + "parents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", + "dev": true, + "requires": { + "path-platform": "0.11.15" + } + }, + "parse-asn1": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", + "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", + "dev": true, + "requires": { + "asn1.js": "4.9.1", + "browserify-aes": "1.0.6", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.0", + "pbkdf2": "3.0.13" + } + }, + "parse-filepath": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.1.tgz", + "integrity": "sha1-FZ1hVdQ5BNFsEO9piRHaHpGWm3M=", + "dev": true, + "requires": { + "is-absolute": "0.2.6", + "map-cache": "0.2.2", + "path-root": "0.1.1" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, + "path-platform": { + "version": "0.11.15", + "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", + "dev": true + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "0.1.2" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, + "pbkdf2": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.13.tgz", + "integrity": "sha512-+dCHxDH+djNtjgWmvVC/my3SYBAKpKNqKSjLkp+GtWWYe4XPE+e/PSD2aCanlEZZnqPk2uekTKNC/ccbwd2X2Q==", + "dev": true, + "requires": { + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.8" + } + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, + "process": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/process/-/process-0.10.1.tgz", + "integrity": "sha1-hCRXzFHP7XLcd1r+6vuMYDQ3JyU=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "public-encrypt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", + "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", + "dev": true, + "requires": { + "bn.js": "4.11.7", + "browserify-rsa": "4.0.1", + "create-hash": "1.1.3", + "parse-asn1": "5.1.0", + "randombytes": "2.0.5" + } + }, + "punycode": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.2.4.tgz", + "integrity": "sha1-VACKyXKux0F13vnLpt9/qdORh0A=", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "randombytes": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz", + "integrity": "sha512-8T7Zn1AhMsQ/HI1SjcCfT/t4ii3eAqco3yOcSzS4mozsOz69lHLsoMXmF9nZgnFanYscnSlUSgs8uZyKzpE6kg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "readable-wrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/readable-wrap/-/readable-wrap-1.0.0.tgz", + "integrity": "sha1-O1ohHGMeEjA6VJkcgGwX564ga/8=", + "dev": true, + "requires": { + "readable-stream": "1.1.14" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "1.4.0" + }, + "dependencies": { + "resolve": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz", + "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", + "dev": true, + "requires": { + "path-parse": "1.0.5" + } + } + } + }, + "regex-cache": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz", + "integrity": "sha1-mxpsNdTQ3871cRrmUejp09cRQUU=", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3", + "is-primitive": "2.0.0" + } + }, + "remove-trailing-separator": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.0.2.tgz", + "integrity": "sha1-abBi2XhyetFNxrVrpKt3L9jXBRE=", + "dev": true + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "resolve": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.7.4.tgz", + "integrity": "sha1-OVqe+ehz+/4SvRRAi9kbuTYAPWk=", + "dev": true + }, + "resolve-dir": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", + "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=", + "dev": true, + "requires": { + "expand-tilde": "1.2.2", + "global-modules": "0.2.3" + } + }, + "rfile": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rfile/-/rfile-1.0.0.tgz", + "integrity": "sha1-WXCM+Qyh50xUw8/Fw2/bmBBDUmE=", + "dev": true, + "requires": { + "callsite": "1.0.0", + "resolve": "0.3.1" + }, + "dependencies": { + "resolve": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.3.1.tgz", + "integrity": "sha1-NMY0R8ZkxwWY0cmxJvxDsqJDEKQ=", + "dev": true + } + } + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", + "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", + "dev": true, + "requires": { + "glob": "7.1.2" + }, + "dependencies": { + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + } + } + }, + "ripemd160": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", + "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", + "dev": true, + "requires": { + "hash-base": "2.0.2", + "inherits": "2.0.3" + } + }, + "ruglify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ruglify/-/ruglify-1.0.0.tgz", + "integrity": "sha1-3Ikw4qlUSidDAcyZcldMDQmGtnU=", + "dev": true, + "requires": { + "rfile": "1.0.0", + "uglify-js": "2.2.5" + }, + "dependencies": { + "uglify-js": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.2.5.tgz", + "integrity": "sha1-puAqcNg5eSuXgEiLe4sYTAlcmcc=", + "dev": true, + "requires": { + "optimist": "0.3.7", + "source-map": "0.1.43" + } + } + } + }, + "runforcover": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/runforcover/-/runforcover-0.0.2.tgz", + "integrity": "sha1-NE8FfY1F0zrrxsyCIEZ49pxIV8w=", + "dev": true, + "requires": { + "bunker": "0.1.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "dev": true + }, + "sequencify": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", + "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", + "dev": true + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, + "sha.js": { + "version": "2.4.8", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.8.tgz", + "integrity": "sha1-NwaMLEdra69ALRSknGf1l5IfY08=", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "shallow-copy": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", + "integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=", + "dev": true + }, + "shasum": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", + "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", + "dev": true, + "requires": { + "json-stable-stringify": "0.0.1", + "sha.js": "2.4.8" + } + }, + "shell-quote": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-0.0.1.tgz", + "integrity": "sha1-GkEZbzwDM8SCMjWT1ohuzxU92YY=", + "dev": true + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "simplesvg": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/simplesvg/-/simplesvg-0.0.10.tgz", + "integrity": "sha1-N9LsGN4sFU3Ztp956K0gvx4eX90=", + "requires": { + "add-event-listener": "0.0.1" + } + }, + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", + "dev": true + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + }, + "sparkles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", + "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", + "dev": true + }, + "stream-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-1.0.0.tgz", + "integrity": "sha1-v5tKv7QrJ011FHnkTg/yZWtvEZM=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "1.1.14" + } + }, + "stream-combiner2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.0.2.tgz", + "integrity": "sha1-unKmtQy/q/qVD8i8h2BL0B62BnE=", + "dev": true, + "requires": { + "duplexer2": "0.0.2", + "through2": "0.5.1" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", + "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "3.0.0" + } + } + } + }, + "stream-consume": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz", + "integrity": "sha1-pB6tGm1ggc63n2WwYZAbbY89HQ8=", + "dev": true + }, + "stream-splicer": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-1.3.2.tgz", + "integrity": "sha1-PARBvhW5v04iYnXm3IOWR0VUZmE=", + "dev": true, + "requires": { + "indexof": "0.0.1", + "inherits": "2.0.3", + "isarray": "0.0.1", + "readable-stream": "1.1.14", + "readable-wrap": "1.0.0", + "through2": "1.1.1" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", + "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", + "dev": true, + "requires": { + "first-chunk-stream": "1.0.0", + "is-utf8": "0.2.1" + } + }, + "subarg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", + "dev": true, + "requires": { + "minimist": "1.2.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "syntax-error": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.3.0.tgz", + "integrity": "sha1-HtkmbE1AvnXcVb+bsct3Biu5bKE=", + "dev": true, + "requires": { + "acorn": "4.0.13" + } + }, + "tap": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/tap/-/tap-0.4.13.tgz", + "integrity": "sha1-OYYTTWdZcn/CIj5hEm7rhyQ6zLw=", + "dev": true, + "requires": { + "buffer-equal": "0.0.2", + "deep-equal": "0.0.0", + "difflet": "0.2.6", + "glob": "3.2.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "nopt": "2.2.1", + "runforcover": "0.0.2", + "slide": "1.1.6", + "yamlish": "0.0.7" + }, + "dependencies": { + "deep-equal": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.0.0.tgz", + "integrity": "sha1-mWedO70EcVb81FDT0B7rkGhpHoM=", + "dev": true + }, + "glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimatch": "0.3.0" + } + }, + "minimatch": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + } + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-1.1.1.tgz", + "integrity": "sha1-CEfLxESfNAVXTb3M2buEG4OsNUU=", + "dev": true, + "requires": { + "readable-stream": "1.1.14", + "xtend": "4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "tildify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "timers-browserify": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", + "dev": true, + "requires": { + "process": "0.11.10" + }, + "dependencies": { + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + } + } + }, + "traverse": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", + "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=", + "dev": true + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "uglify-js": { + "version": "2.4.24", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.24.tgz", + "integrity": "sha1-+tV1XB4Vd2WLsG/5q25UjJW+vW4=", + "dev": true, + "requires": { + "async": "0.2.10", + "source-map": "0.1.34", + "uglify-to-browserify": "1.0.2", + "yargs": "3.5.4" + }, + "dependencies": { + "source-map": { + "version": "0.1.34", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.34.tgz", + "integrity": "sha1-p8/omux7FoLDsZjQrPtH19CQVms=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "uglify-save-license": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/uglify-save-license/-/uglify-save-license-0.4.1.tgz", + "integrity": "sha1-lXJsF8xv0XHDYX479NjYKqjEzOE=", + "dev": true + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true + }, + "umd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/umd/-/umd-2.1.0.tgz", + "integrity": "sha1-SmMHt2LxfwLSAbX6FU5nM5bCY88=", + "dev": true, + "requires": { + "rfile": "1.0.0", + "ruglify": "1.0.0", + "through": "2.3.8", + "uglify-js": "2.4.24" + } + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, + "unique-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", + "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", + "dev": true + }, + "url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true, + "requires": { + "user-home": "1.1.1" + } + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "1.0.2", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vinyl-buffer/-/vinyl-buffer-1.0.0.tgz", + "integrity": "sha1-ygZ+oIQx1QdyKx3lCD9gJhbrwjQ=", + "dev": true, + "requires": { + "bl": "0.9.5", + "through2": "0.6.5" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "vinyl-fs": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", + "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", + "dev": true, + "requires": { + "defaults": "1.0.3", + "glob-stream": "3.1.18", + "glob-watcher": "0.0.6", + "graceful-fs": "3.0.11", + "mkdirp": "0.5.1", + "strip-bom": "1.0.0", + "through2": "0.6.5", + "vinyl": "0.4.6" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "0.2.0", + "clone-stats": "0.0.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "vinyl-source-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-1.1.0.tgz", + "integrity": "sha1-RMvlEIIFJ53rDFZTwJSiiHk4sas=", + "dev": true, + "requires": { + "through2": "0.6.5", + "vinyl": "0.4.6" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "0.2.0", + "clone-stats": "0.0.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", + "dev": true, + "requires": { + "source-map": "0.5.6" + }, + "dependencies": { + "source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", + "dev": true + } + } + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "requires": { + "indexof": "0.0.1" + } + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xtend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", + "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", + "dev": true + }, + "yamlish": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/yamlish/-/yamlish-0.0.7.tgz", + "integrity": "sha1-tK+aHcxjYYhzw9bkUewyE8OaV/s=", + "dev": true + }, + "yargs": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.5.4.tgz", + "integrity": "sha1-2K/49mXpTDS9JZvevRv68N3TU2E=", + "dev": true, + "requires": { + "camelcase": "1.2.1", + "decamelize": "1.2.0", + "window-size": "0.1.0", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + } + } + } + } +} diff --git a/src/View/webglGraphics.js b/src/View/webglGraphics.js index 7a2fd4f..7066ef0 100644 --- a/src/View/webglGraphics.js +++ b/src/View/webglGraphics.js @@ -290,6 +290,12 @@ function webglGraphics(options) { return this; }, + /** + * Resizes the graphic without resetting the scale. + * Useful with viva graph in a dynamic container + */ + updateSize: updateSize, + /** * Called by Viva.Graph.View.renderer to let concrete graphic output * provider prepare to render. From 42af85f27d023675fc1b9483dfb153e338bf0f78 Mon Sep 17 00:00:00 2001 From: jlazar Date: Mon, 7 Aug 2017 15:00:35 -0400 Subject: [PATCH 239/276] removing package-lock --- package-lock.json | 3681 --------------------------------------------- 1 file changed, 3681 deletions(-) delete mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 549379a..0000000 --- a/package-lock.json +++ /dev/null @@ -1,3681 +0,0 @@ -{ - "name": "vivagraphjs", - "version": "0.9.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "abbrev": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz", - "integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=", - "dev": true - }, - "acorn": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", - "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", - "dev": true - }, - "add-event-listener": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/add-event-listener/-/add-event-listener-0.0.1.tgz", - "integrity": "sha1-p2Ip68ZMiu+uIEoWJzovJVq+otA=" - }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, - "requires": { - "kind-of": "3.2.2", - "longest": "1.0.1", - "repeat-string": "1.6.1" - } - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "requires": { - "arr-flatten": "1.1.0" - } - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "array-differ": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", - "dev": true - }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true - }, - "array-slice": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.0.0.tgz", - "integrity": "sha1-5zA08A3MH0CHYAj9IP6ud71LfC8=", - "dev": true - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "1.0.3" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "asn1.js": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.1.tgz", - "integrity": "sha1-SLokC0WpKA6UdImQull9IWYX/UA=", - "dev": true, - "requires": { - "bn.js": "4.11.7", - "inherits": "2.0.3", - "minimalistic-assert": "1.0.0" - } - }, - "assert": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.3.0.tgz", - "integrity": "sha1-A5OaYiWCqBLMICMgoLmlbJuBWEk=", - "dev": true, - "requires": { - "util": "0.10.3" - } - }, - "astw": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/astw/-/astw-2.2.0.tgz", - "integrity": "sha1-e9QXhNMkk5h66yOba04cV6hzuRc=", - "dev": true, - "requires": { - "acorn": "4.0.13" - } - }, - "async": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "Base64": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/Base64/-/Base64-0.2.1.tgz", - "integrity": "sha1-ujpCMHCOGGcFBl5mur3Uw1z2ACg=", - "dev": true - }, - "base64-js": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", - "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=", - "dev": true - }, - "beeper": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", - "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", - "dev": true - }, - "bl": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", - "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", - "dev": true, - "requires": { - "readable-stream": "1.0.34" - }, - "dependencies": { - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - } - } - }, - "bn.js": { - "version": "4.11.7", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.7.tgz", - "integrity": "sha512-LxFiV5mefv0ley0SzqkOPR1bC4EbpPx8LkOz5vMe/Yi15t5hzwgO/G+tc7wOtL4PZTYjwHu8JnEiSLumuSjSfA==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", - "dev": true, - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "requires": { - "expand-range": "1.8.2", - "preserve": "0.2.0", - "repeat-element": "1.1.2" - } - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true - }, - "browser-pack": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-3.2.0.tgz", - "integrity": "sha1-+qHLxBSHsazEdH43PhFIrf/Q4tk=", - "dev": true, - "requires": { - "combine-source-map": "0.3.0", - "concat-stream": "1.4.10", - "defined": "0.0.0", - "JSONStream": "0.8.4", - "through2": "0.5.1", - "umd": "2.1.0" - }, - "dependencies": { - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "through2": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", - "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "3.0.0" - } - } - } - }, - "browser-resolve": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", - "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=", - "dev": true, - "requires": { - "resolve": "1.1.7" - }, - "dependencies": { - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - } - } - }, - "browserify": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/browserify/-/browserify-8.1.3.tgz", - "integrity": "sha1-8zpUmjpsNoIZsHX9z+bfGV4Empo=", - "dev": true, - "requires": { - "assert": "1.3.0", - "browser-pack": "3.2.0", - "browser-resolve": "1.11.2", - "browserify-zlib": "0.1.4", - "buffer": "3.6.0", - "builtins": "0.0.7", - "commondir": "0.0.1", - "concat-stream": "1.4.10", - "console-browserify": "1.1.0", - "constants-browserify": "0.0.1", - "crypto-browserify": "3.11.1", - "deep-equal": "0.2.2", - "defined": "0.0.0", - "deps-sort": "1.3.9", - "domain-browser": "1.1.7", - "duplexer2": "0.0.2", - "events": "1.0.2", - "glob": "4.5.3", - "http-browserify": "1.7.0", - "https-browserify": "0.0.1", - "inherits": "2.0.3", - "insert-module-globals": "6.6.3", - "isarray": "0.0.1", - "JSONStream": "0.8.4", - "labeled-stream-splicer": "1.0.2", - "module-deps": "3.9.1", - "os-browserify": "0.1.2", - "parents": "1.0.1", - "path-browserify": "0.0.0", - "process": "0.10.1", - "punycode": "1.2.4", - "querystring-es3": "0.2.1", - "readable-stream": "1.1.14", - "resolve": "0.7.4", - "shallow-copy": "0.0.1", - "shasum": "1.0.2", - "shell-quote": "0.0.1", - "stream-browserify": "1.0.0", - "string_decoder": "0.10.31", - "subarg": "1.0.0", - "syntax-error": "1.3.0", - "through2": "1.1.1", - "timers-browserify": "1.4.2", - "tty-browserify": "0.0.0", - "umd": "2.1.0", - "url": "0.10.3", - "util": "0.10.3", - "vm-browserify": "0.0.4", - "xtend": "3.0.0" - } - }, - "browserify-aes": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.0.6.tgz", - "integrity": "sha1-Xncl297x/Vkw1OurSFZ85FHEigo=", - "dev": true, - "requires": { - "buffer-xor": "1.0.3", - "cipher-base": "1.0.4", - "create-hash": "1.1.3", - "evp_bytestokey": "1.0.0", - "inherits": "2.0.3" - } - }, - "browserify-cipher": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", - "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", - "dev": true, - "requires": { - "browserify-aes": "1.0.6", - "browserify-des": "1.0.0", - "evp_bytestokey": "1.0.0" - } - }, - "browserify-des": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", - "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", - "dev": true, - "requires": { - "cipher-base": "1.0.4", - "des.js": "1.0.0", - "inherits": "2.0.3" - } - }, - "browserify-rsa": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true, - "requires": { - "bn.js": "4.11.7", - "randombytes": "2.0.5" - } - }, - "browserify-sign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", - "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "dev": true, - "requires": { - "bn.js": "4.11.7", - "browserify-rsa": "4.0.1", - "create-hash": "1.1.3", - "create-hmac": "1.1.6", - "elliptic": "6.4.0", - "inherits": "2.0.3", - "parse-asn1": "5.1.0" - } - }, - "browserify-zlib": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", - "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", - "dev": true, - "requires": { - "pako": "0.2.9" - } - }, - "buffer": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz", - "integrity": "sha1-pyyTb3e5a/UvX357RnGAYoVR3vs=", - "dev": true, - "requires": { - "base64-js": "0.0.8", - "ieee754": "1.1.8", - "isarray": "1.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } - } - }, - "buffer-equal": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.2.tgz", - "integrity": "sha1-7Lt5D1aNQAmKYkK1SAXHWAXrk48=", - "dev": true - }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true - }, - "builtins": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-0.0.7.tgz", - "integrity": "sha1-NVIZzWzxjb58Acx/0tznZc/cVJo=", - "dev": true - }, - "bunker": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/bunker/-/bunker-0.1.2.tgz", - "integrity": "sha1-yImSRkqOKm7ehpMDdfkrWAd++Xw=", - "dev": true, - "requires": { - "burrito": "0.2.12" - } - }, - "burrito": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/burrito/-/burrito-0.2.12.tgz", - "integrity": "sha1-0NbmrIHV6ZeJxvpKzLCwAx6lT2s=", - "dev": true, - "requires": { - "traverse": "0.5.2", - "uglify-js": "1.1.1" - }, - "dependencies": { - "traverse": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.5.2.tgz", - "integrity": "sha1-4gPFjV9/DjfbbnTArLkpuwm2HYU=", - "dev": true - }, - "uglify-js": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-1.1.1.tgz", - "integrity": "sha1-7nGpfEzv0GoamyBDfzQRiYKqA1s=", - "dev": true - } - } - }, - "callsite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", - "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", - "dev": true - }, - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true - }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, - "requires": { - "align-text": "0.1.4", - "lazy-cache": "1.0.4" - } - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, - "charm": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/charm/-/charm-0.1.2.tgz", - "integrity": "sha1-BsIe7RobBq62dVPNxT4jJ0usIpY=", - "dev": true - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, - "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.1" - } - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, - "requires": { - "center-align": "0.1.3", - "right-align": "0.1.3", - "wordwrap": "0.0.2" - }, - "dependencies": { - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true - } - } - }, - "clone": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", - "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=", - "dev": true - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "combine-source-map": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.3.0.tgz", - "integrity": "sha1-2edPWT2c1DgHMSy12EbUUe+qnrc=", - "dev": true, - "requires": { - "convert-source-map": "0.3.5", - "inline-source-map": "0.3.1", - "source-map": "0.1.43" - } - }, - "commondir": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-0.0.1.tgz", - "integrity": "sha1-ifAP3NUbUZxXhzP+xWPmptp/W+I=", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.4.10", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.4.10.tgz", - "integrity": "sha1-rMO79WAsuMyYDGrIQPp9hgPj7zY=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "1.1.14", - "typedarray": "0.0.6" - } - }, - "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true, - "requires": { - "date-now": "0.1.4" - } - }, - "constants-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-0.0.1.tgz", - "integrity": "sha1-kld9tSe6bEzwpFaNhLwDH0QeIfI=", - "dev": true - }, - "convert-source-map": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-0.3.5.tgz", - "integrity": "sha1-8dgClQr33SYxof6+BZZVDIarMZA=", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "create-ecdh": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", - "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", - "dev": true, - "requires": { - "bn.js": "4.11.7", - "elliptic": "6.4.0" - } - }, - "create-hash": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", - "dev": true, - "requires": { - "cipher-base": "1.0.4", - "inherits": "2.0.3", - "ripemd160": "2.0.1", - "sha.js": "2.4.8" - } - }, - "create-hmac": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", - "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", - "dev": true, - "requires": { - "cipher-base": "1.0.4", - "create-hash": "1.1.3", - "inherits": "2.0.3", - "ripemd160": "2.0.1", - "safe-buffer": "5.1.1", - "sha.js": "2.4.8" - } - }, - "crypto-browserify": { - "version": "3.11.1", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.11.1.tgz", - "integrity": "sha512-Na7ZlwCOqoaW5RwUK1WpXws2kv8mNhWdTlzob0UXulk6G9BDbyiJaGTYBIX61Ozn9l1EPPJpICZb4DaOpT9NlQ==", - "dev": true, - "requires": { - "browserify-cipher": "1.0.0", - "browserify-sign": "4.0.4", - "create-ecdh": "4.0.0", - "create-hash": "1.1.3", - "create-hmac": "1.1.6", - "diffie-hellman": "5.0.2", - "inherits": "2.0.3", - "pbkdf2": "3.0.13", - "public-encrypt": "4.0.0", - "randombytes": "2.0.5" - } - }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", - "dev": true - }, - "dateformat": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.0.0.tgz", - "integrity": "sha1-J0Pjq7XD/CRi5SfcpEXgTp9N7hc=", - "dev": true - }, - "deap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/deap/-/deap-1.0.0.tgz", - "integrity": "sha1-sUi/gkMKJ2mbdIOgPra2dYW/yIg=", - "dev": true - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "deep-equal": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.2.2.tgz", - "integrity": "sha1-hLdFiW80xoTpjyzg5Cq69Du6AX0=", - "dev": true - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "requires": { - "clone": "1.0.2" - } - }, - "defined": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-0.0.0.tgz", - "integrity": "sha1-817qfXBekzuvE7LwOz+D2SFAOz4=", - "dev": true - }, - "del": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/del/-/del-1.2.1.tgz", - "integrity": "sha1-rtblvNfLcyXfNPVjEl+iZbLBoBQ=", - "dev": true, - "requires": { - "each-async": "1.1.1", - "globby": "2.1.0", - "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.0", - "object-assign": "3.0.0", - "rimraf": "2.6.1" - } - }, - "deprecated": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", - "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", - "dev": true - }, - "deps-sort": { - "version": "1.3.9", - "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-1.3.9.tgz", - "integrity": "sha1-Kd//U+F7Nq7K51MK27v2IsLtGnE=", - "dev": true, - "requires": { - "JSONStream": "1.3.1", - "shasum": "1.0.2", - "subarg": "1.0.0", - "through2": "1.1.1" - }, - "dependencies": { - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", - "dev": true - }, - "JSONStream": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.1.tgz", - "integrity": "sha1-cH92HgHa6eFvG8+TcDt4xwlmV5o=", - "dev": true, - "requires": { - "jsonparse": "1.3.1", - "through": "2.3.8" - } - } - } - }, - "des.js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", - "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "minimalistic-assert": "1.0.0" - } - }, - "detect-file": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-0.1.0.tgz", - "integrity": "sha1-STXe39lIhkjgBrASlWbpOGcR6mM=", - "dev": true, - "requires": { - "fs-exists-sync": "0.1.0" - } - }, - "detective": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/detective/-/detective-4.5.0.tgz", - "integrity": "sha1-blqMaybmx6JUsca210kNmOyR7dE=", - "dev": true, - "requires": { - "acorn": "4.0.13", - "defined": "1.0.0" - }, - "dependencies": { - "defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", - "dev": true - } - } - }, - "diffie-hellman": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", - "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", - "dev": true, - "requires": { - "bn.js": "4.11.7", - "miller-rabin": "4.0.0", - "randombytes": "2.0.5" - } - }, - "difflet": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/difflet/-/difflet-0.2.6.tgz", - "integrity": "sha1-qyOzH1ZJtvqo49KsvTNEZzZcpvo=", - "dev": true, - "requires": { - "charm": "0.1.2", - "deep-is": "0.1.3", - "traverse": "0.6.6" - } - }, - "domain-browser": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", - "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", - "dev": true - }, - "duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true, - "requires": { - "readable-stream": "1.1.14" - } - }, - "each-async": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/each-async/-/each-async-1.1.1.tgz", - "integrity": "sha1-3uUim98KtrogEqOV4bhpq/iBNHM=", - "dev": true, - "requires": { - "onetime": "1.1.0", - "set-immediate-shim": "1.0.1" - } - }, - "elliptic": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", - "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", - "dev": true, - "requires": { - "bn.js": "4.11.7", - "brorand": "1.1.0", - "hash.js": "1.1.3", - "hmac-drbg": "1.0.1", - "inherits": "2.0.3", - "minimalistic-assert": "1.0.0", - "minimalistic-crypto-utils": "1.0.1" - } - }, - "end-of-stream": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", - "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", - "dev": true, - "requires": { - "once": "1.3.3" - }, - "dependencies": { - "once": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "dev": true, - "requires": { - "wrappy": "1.0.2" - } - } - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "events": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/events/-/events-1.0.2.tgz", - "integrity": "sha1-dYSdz+k9EPsFfDAFWv29UdBqjiQ=", - "dev": true - }, - "evp_bytestokey": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.0.tgz", - "integrity": "sha1-SXtmrZ/vZc18CKYYCCS6FHa2blM=", - "dev": true, - "requires": { - "create-hash": "1.1.3" - } - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, - "requires": { - "is-posix-bracket": "0.1.1" - } - }, - "expand-range": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true, - "requires": { - "fill-range": "2.2.3" - } - }, - "expand-tilde": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", - "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", - "dev": true, - "requires": { - "os-homedir": "1.0.2" - } - }, - "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", - "dev": true - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - }, - "fancy-log": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.0.tgz", - "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "time-stamp": "1.1.0" - } - }, - "filename-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true - }, - "fill-range": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", - "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", - "dev": true, - "requires": { - "is-number": "2.1.0", - "isobject": "2.1.0", - "randomatic": "1.1.7", - "repeat-element": "1.1.2", - "repeat-string": "1.6.1" - } - }, - "find-index": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", - "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", - "dev": true - }, - "findup-sync": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.4.3.tgz", - "integrity": "sha1-QAQ5Kee8YK3wt/SCfExudaDeyhI=", - "dev": true, - "requires": { - "detect-file": "0.1.0", - "is-glob": "2.0.1", - "micromatch": "2.3.11", - "resolve-dir": "0.1.1" - } - }, - "fined": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", - "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", - "dev": true, - "requires": { - "expand-tilde": "2.0.2", - "is-plain-object": "2.0.4", - "object.defaults": "1.1.0", - "object.pick": "1.2.0", - "parse-filepath": "1.0.1" - }, - "dependencies": { - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "1.0.1" - } - } - } - }, - "first-chunk-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", - "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", - "dev": true - }, - "flagged-respawn": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-0.3.2.tgz", - "integrity": "sha1-/xke3c1wiKZ1smEP/8l2vpuAdLU=", - "dev": true - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, - "requires": { - "for-in": "1.0.2" - } - }, - "fs-exists-sync": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", - "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "gaze": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", - "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", - "dev": true, - "requires": { - "globule": "0.1.0" - } - }, - "gintersect": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/gintersect/-/gintersect-0.1.0.tgz", - "integrity": "sha1-moy2qAt9bpVawzUVSVsSEmJ7GBY=" - }, - "glob": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", - "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", - "dev": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "2.0.10", - "once": "1.4.0" - } - }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true, - "requires": { - "glob-parent": "2.0.0", - "is-glob": "2.0.1" - } - }, - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "2.0.1" - } - }, - "glob-stream": { - "version": "3.1.18", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", - "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", - "dev": true, - "requires": { - "glob": "4.5.3", - "glob2base": "0.0.12", - "minimatch": "2.0.10", - "ordered-read-streams": "0.1.0", - "through2": "0.6.5", - "unique-stream": "1.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - } - } - }, - "glob-watcher": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", - "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", - "dev": true, - "requires": { - "gaze": "0.5.2" - } - }, - "glob2base": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", - "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", - "dev": true, - "requires": { - "find-index": "0.1.1" - } - }, - "global-modules": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", - "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=", - "dev": true, - "requires": { - "global-prefix": "0.1.5", - "is-windows": "0.2.0" - } - }, - "global-prefix": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", - "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=", - "dev": true, - "requires": { - "homedir-polyfill": "1.0.1", - "ini": "1.3.4", - "is-windows": "0.2.0", - "which": "1.3.0" - } - }, - "globby": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-2.1.0.tgz", - "integrity": "sha1-npGSvNM/Srak+JTl5+qLcTITxII=", - "dev": true, - "requires": { - "array-union": "1.0.2", - "async": "1.5.2", - "glob": "5.0.15", - "object-assign": "3.0.0" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "2.0.10", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - } - } - }, - "globule": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", - "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", - "dev": true, - "requires": { - "glob": "3.1.21", - "lodash": "1.0.2", - "minimatch": "0.2.14" - }, - "dependencies": { - "glob": { - "version": "3.1.21", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", - "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", - "dev": true, - "requires": { - "graceful-fs": "1.2.3", - "inherits": "1.0.2", - "minimatch": "0.2.14" - } - }, - "graceful-fs": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", - "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", - "dev": true - }, - "inherits": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", - "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", - "dev": true - }, - "minimatch": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", - "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "dev": true, - "requires": { - "lru-cache": "2.7.3", - "sigmund": "1.0.1" - } - } - } - }, - "glogg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz", - "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", - "dev": true, - "requires": { - "sparkles": "1.0.0" - } - }, - "graceful-fs": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", - "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", - "dev": true, - "requires": { - "natives": "1.1.0" - } - }, - "gulp": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", - "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", - "dev": true, - "requires": { - "archy": "1.0.0", - "chalk": "1.1.3", - "deprecated": "0.0.1", - "gulp-util": "3.0.8", - "interpret": "1.0.3", - "liftoff": "2.3.0", - "minimist": "1.2.0", - "orchestrator": "0.3.8", - "pretty-hrtime": "1.0.3", - "semver": "4.3.6", - "tildify": "1.2.0", - "v8flags": "2.1.1", - "vinyl-fs": "0.3.14" - } - }, - "gulp-rename": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.2.2.tgz", - "integrity": "sha1-OtRCh2PwXidk3sHGfYaNsnVoeBc=", - "dev": true - }, - "gulp-run": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/gulp-run/-/gulp-run-1.7.1.tgz", - "integrity": "sha1-4XwKy3wwtuKu7iPAREKpbAys7/o=", - "dev": true, - "requires": { - "gulp-util": "3.0.8", - "lodash.defaults": "4.2.0", - "lodash.template": "4.4.0", - "vinyl": "0.4.6" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "lodash.template": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", - "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", - "dev": true, - "requires": { - "lodash._reinterpolate": "3.0.0", - "lodash.templatesettings": "4.1.0" - } - }, - "lodash.templatesettings": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", - "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", - "dev": true, - "requires": { - "lodash._reinterpolate": "3.0.0" - } - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" - } - } - } - }, - "gulp-uglify": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-1.5.4.tgz", - "integrity": "sha1-UkeI2HZm0J+dDCH7IXf5ADmmWMk=", - "dev": true, - "requires": { - "deap": "1.0.0", - "fancy-log": "1.3.0", - "gulp-util": "3.0.8", - "isobject": "2.1.0", - "through2": "2.0.3", - "uglify-js": "2.6.4", - "uglify-save-license": "0.4.1", - "vinyl-sourcemaps-apply": "0.2.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "source-map": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", - "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", - "dev": true - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - }, - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, - "requires": { - "readable-stream": "2.3.3", - "xtend": "4.0.1" - } - }, - "uglify-js": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.6.4.tgz", - "integrity": "sha1-ZeovswWck5RpLxX+2HwrNsFrmt8=", - "dev": true, - "requires": { - "async": "0.2.10", - "source-map": "0.5.6", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" - } - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "requires": { - "camelcase": "1.2.1", - "cliui": "2.1.0", - "decamelize": "1.2.0", - "window-size": "0.1.0" - } - } - } - }, - "gulp-util": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", - "dev": true, - "requires": { - "array-differ": "1.0.0", - "array-uniq": "1.0.3", - "beeper": "1.1.1", - "chalk": "1.1.3", - "dateformat": "2.0.0", - "fancy-log": "1.3.0", - "gulplog": "1.0.0", - "has-gulplog": "0.1.0", - "lodash._reescape": "3.0.0", - "lodash._reevaluate": "3.0.0", - "lodash._reinterpolate": "3.0.0", - "lodash.template": "3.6.2", - "minimist": "1.2.0", - "multipipe": "0.1.2", - "object-assign": "3.0.0", - "replace-ext": "0.0.1", - "through2": "2.0.3", - "vinyl": "0.5.3" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - }, - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, - "requires": { - "readable-stream": "2.3.3", - "xtend": "4.0.1" - } - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - } - } - }, - "gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "requires": { - "glogg": "1.0.0" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "has-gulplog": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", - "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true, - "requires": { - "sparkles": "1.0.0" - } - }, - "hash-base": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", - "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, - "hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "dev": true, - "requires": { - "inherits": "2.0.3", - "minimalistic-assert": "1.0.0" - } - }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, - "requires": { - "hash.js": "1.1.3", - "minimalistic-assert": "1.0.0", - "minimalistic-crypto-utils": "1.0.1" - } - }, - "homedir-polyfill": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", - "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", - "dev": true, - "requires": { - "parse-passwd": "1.0.0" - } - }, - "http-browserify": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/http-browserify/-/http-browserify-1.7.0.tgz", - "integrity": "sha1-M3la3nLfiKz7/TZ3PO/tp2RzWyA=", - "dev": true, - "requires": { - "Base64": "0.2.1", - "inherits": "2.0.3" - } - }, - "https-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", - "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=", - "dev": true - }, - "ieee754": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", - "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=", - "dev": true - }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "ini": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", - "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", - "dev": true - }, - "inline-source-map": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.3.1.tgz", - "integrity": "sha1-pSi1FOaJ/OkNswiehw2S9Sestes=", - "dev": true, - "requires": { - "source-map": "0.3.0" - }, - "dependencies": { - "source-map": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.3.0.tgz", - "integrity": "sha1-hYb7mloAXltQHiHNGLbyG0V60fk=", - "dev": true, - "requires": { - "amdefine": "1.0.1" - } - } - } - }, - "insert-module-globals": { - "version": "6.6.3", - "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-6.6.3.tgz", - "integrity": "sha1-IGOOKaMPntHKLjqCX7wsulJG3fw=", - "dev": true, - "requires": { - "combine-source-map": "0.6.1", - "concat-stream": "1.4.10", - "is-buffer": "1.1.5", - "JSONStream": "1.3.1", - "lexical-scope": "1.2.0", - "process": "0.11.10", - "through2": "1.1.1", - "xtend": "4.0.1" - }, - "dependencies": { - "combine-source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.6.1.tgz", - "integrity": "sha1-m0oJwxYDPXaODxHgKfonMOB5rZY=", - "dev": true, - "requires": { - "convert-source-map": "1.1.3", - "inline-source-map": "0.5.0", - "lodash.memoize": "3.0.4", - "source-map": "0.4.4" - } - }, - "convert-source-map": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", - "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", - "dev": true - }, - "inline-source-map": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.5.0.tgz", - "integrity": "sha1-Skxd2OT7Xps82mDIIt+tyu5m4K8=", - "dev": true, - "requires": { - "source-map": "0.4.4" - } - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", - "dev": true - }, - "JSONStream": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.1.tgz", - "integrity": "sha1-cH92HgHa6eFvG8+TcDt4xwlmV5o=", - "dev": true, - "requires": { - "jsonparse": "1.3.1", - "through": "2.3.8" - } - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true - }, - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": "1.0.1" - } - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - } - } - }, - "interpret": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.3.tgz", - "integrity": "sha1-y8NcYu7uc/Gat7EKgBURQBr8D5A=", - "dev": true - }, - "is-absolute": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.2.6.tgz", - "integrity": "sha1-IN5p89uULvLYe5wto28XIjWxtes=", - "dev": true, - "requires": { - "is-relative": "0.2.1", - "is-windows": "0.2.0" - } - }, - "is-buffer": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", - "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", - "dev": true - }, - "is-dotfile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true - }, - "is-equal-shallow": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true, - "requires": { - "is-primitive": "2.0.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - }, - "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - } - }, - "is-path-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", - "dev": true - }, - "is-path-in-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", - "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", - "dev": true, - "requires": { - "is-path-inside": "1.0.0" - } - }, - "is-path-inside": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", - "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", - "dev": true, - "requires": { - "path-is-inside": "1.0.2" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "is-posix-bracket": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true - }, - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true - }, - "is-relative": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz", - "integrity": "sha1-0n9MfVFtF1+2ENuEu+7yPDvJeqU=", - "dev": true, - "requires": { - "is-unc-path": "0.1.2" - } - }, - "is-unc-path": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-0.1.2.tgz", - "integrity": "sha1-arBTpyVzwQJQ/0FqOBTDUXivObk=", - "dev": true, - "requires": { - "unc-path-regex": "0.1.2" - } - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-windows": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", - "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=", - "dev": true - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } - } - }, - "json-stable-stringify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", - "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", - "dev": true, - "requires": { - "jsonify": "0.0.0" - } - }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, - "jsonparse": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz", - "integrity": "sha1-MwVCrT8KZUZlt3jz6y2an6UHrGQ=", - "dev": true - }, - "JSONStream": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.8.4.tgz", - "integrity": "sha1-kWV9/m/4V0gwZhMrRhi2Lo9Ih70=", - "dev": true, - "requires": { - "jsonparse": "0.0.5", - "through": "2.3.8" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.5" - } - }, - "labeled-stream-splicer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-1.0.2.tgz", - "integrity": "sha1-RhUzFTd4SYHo/SZOHzpDTE4N3WU=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "isarray": "0.0.1", - "stream-splicer": "1.3.2" - } - }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true - }, - "lexical-scope": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/lexical-scope/-/lexical-scope-1.2.0.tgz", - "integrity": "sha1-/Ope3HBKSzqHls3KQZw6CvryLfQ=", - "dev": true, - "requires": { - "astw": "2.2.0" - } - }, - "liftoff": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.3.0.tgz", - "integrity": "sha1-qY8v9nGD2Lp8+soQVIvX/wVQs4U=", - "dev": true, - "requires": { - "extend": "3.0.1", - "findup-sync": "0.4.3", - "fined": "1.1.0", - "flagged-respawn": "0.3.2", - "lodash.isplainobject": "4.0.6", - "lodash.isstring": "4.0.1", - "lodash.mapvalues": "4.6.0", - "rechoir": "0.6.2", - "resolve": "1.4.0" - }, - "dependencies": { - "resolve": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz", - "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", - "dev": true, - "requires": { - "path-parse": "1.0.5" - } - } - } - }, - "lodash": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", - "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", - "dev": true - }, - "lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", - "dev": true - }, - "lodash._basetostring": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", - "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", - "dev": true - }, - "lodash._basevalues": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", - "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", - "dev": true - }, - "lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", - "dev": true - }, - "lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", - "dev": true - }, - "lodash._reescape": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", - "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", - "dev": true - }, - "lodash._reevaluate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", - "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", - "dev": true - }, - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", - "dev": true - }, - "lodash._root": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", - "dev": true - }, - "lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", - "dev": true - }, - "lodash.escape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", - "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "dev": true, - "requires": { - "lodash._root": "3.0.1" - } - }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", - "dev": true - }, - "lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", - "dev": true - }, - "lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", - "dev": true - }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true, - "requires": { - "lodash._getnative": "3.9.1", - "lodash.isarguments": "3.1.0", - "lodash.isarray": "3.0.4" - } - }, - "lodash.mapvalues": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", - "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=", - "dev": true - }, - "lodash.memoize": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", - "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=", - "dev": true - }, - "lodash.restparam": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", - "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", - "dev": true - }, - "lodash.template": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true, - "requires": { - "lodash._basecopy": "3.0.1", - "lodash._basetostring": "3.0.1", - "lodash._basevalues": "3.0.0", - "lodash._isiterateecall": "3.0.9", - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0", - "lodash.keys": "3.1.2", - "lodash.restparam": "3.6.1", - "lodash.templatesettings": "3.1.1" - } - }, - "lodash.templatesettings": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", - "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true, - "requires": { - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0" - } - }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true - }, - "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", - "dev": true - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "2.0.0", - "array-unique": "0.2.1", - "braces": "1.8.5", - "expand-brackets": "0.1.5", - "extglob": "0.3.2", - "filename-regex": "2.0.1", - "is-extglob": "1.0.0", - "is-glob": "2.0.1", - "kind-of": "3.2.2", - "normalize-path": "2.1.1", - "object.omit": "2.0.1", - "parse-glob": "3.0.4", - "regex-cache": "0.4.3" - } - }, - "miller-rabin": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.0.tgz", - "integrity": "sha1-SmL7HUKTPAVYOYL0xxb2+55sbT0=", - "dev": true, - "requires": { - "bn.js": "4.11.7", - "brorand": "1.1.0" - } - }, - "minimalistic-assert": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", - "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=", - "dev": true - }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true - }, - "minimatch": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", - "dev": true, - "requires": { - "brace-expansion": "1.1.8" - } - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - } - } - }, - "module-deps": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-3.9.1.tgz", - "integrity": "sha1-6nXK+RmQkNJbDVUStaysuW5/h/M=", - "dev": true, - "requires": { - "browser-resolve": "1.11.2", - "concat-stream": "1.4.10", - "defined": "1.0.0", - "detective": "4.5.0", - "duplexer2": "0.0.2", - "inherits": "2.0.3", - "JSONStream": "1.3.1", - "parents": "1.0.1", - "readable-stream": "1.1.14", - "resolve": "1.4.0", - "stream-combiner2": "1.0.2", - "subarg": "1.0.0", - "through2": "1.1.1", - "xtend": "4.0.1" - }, - "dependencies": { - "defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", - "dev": true - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", - "dev": true - }, - "JSONStream": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.1.tgz", - "integrity": "sha1-cH92HgHa6eFvG8+TcDt4xwlmV5o=", - "dev": true, - "requires": { - "jsonparse": "1.3.1", - "through": "2.3.8" - } - }, - "resolve": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz", - "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", - "dev": true, - "requires": { - "path-parse": "1.0.5" - } - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - } - } - }, - "multipipe": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", - "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", - "dev": true, - "requires": { - "duplexer2": "0.0.2" - } - }, - "natives": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.0.tgz", - "integrity": "sha1-6f+EFBimsux6SV6TmYT3jxY+bjE=", - "dev": true - }, - "ngraph.centrality": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ngraph.centrality/-/ngraph.centrality-0.1.3.tgz", - "integrity": "sha1-bKB7QXmv8AfYSY7e8lZoizfYdp0=" - }, - "ngraph.events": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/ngraph.events/-/ngraph.events-0.0.3.tgz", - "integrity": "sha1-OPVTFvPSB61jH/lPZiLKjywOh9A=" - }, - "ngraph.expose": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/ngraph.expose/-/ngraph.expose-0.0.0.tgz", - "integrity": "sha1-dGw0kDo4SMRdAzsUvGRhnqhf5ao=" - }, - "ngraph.forcelayout": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ngraph.forcelayout/-/ngraph.forcelayout-0.1.2.tgz", - "integrity": "sha1-PC4SJ/KRSLqyn8WLweg3SfYdS8U=", - "requires": { - "ngraph.events": "0.0.3", - "ngraph.physics.simulator": "0.1.1" - } - }, - "ngraph.fromjson": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/ngraph.fromjson/-/ngraph.fromjson-0.1.7.tgz", - "integrity": "sha1-VXEnCsj+ED6xaEQUbolIrUIhnHM=", - "requires": { - "ngraph.graph": "0.0.11" - } - }, - "ngraph.generators": { - "version": "0.0.15", - "resolved": "https://registry.npmjs.org/ngraph.generators/-/ngraph.generators-0.0.15.tgz", - "integrity": "sha1-GgnH6S2IPXi8gWwGwvZkC0X0z/I=", - "requires": { - "ngraph.graph": "0.0.11", - "ngraph.random": "0.0.1" - } - }, - "ngraph.graph": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/ngraph.graph/-/ngraph.graph-0.0.11.tgz", - "integrity": "sha1-nxCnJn71l3Q5rFB7r8un9O1yhAE=", - "requires": { - "ngraph.events": "0.0.3" - } - }, - "ngraph.merge": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/ngraph.merge/-/ngraph.merge-0.0.1.tgz", - "integrity": "sha1-5OgM43WBo8lrF9VF46Q8hUNLkCU=" - }, - "ngraph.physics.primitives": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ngraph.physics.primitives/-/ngraph.physics.primitives-0.0.7.tgz", - "integrity": "sha1-Xcnhebofkubex3SwHNaJFBILeVs=" - }, - "ngraph.physics.simulator": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ngraph.physics.simulator/-/ngraph.physics.simulator-0.1.1.tgz", - "integrity": "sha1-h5RmUATQJbnkIyEV/O/9l7+sCK0=", - "requires": { - "ngraph.events": "0.0.3", - "ngraph.expose": "0.0.0", - "ngraph.merge": "0.0.1", - "ngraph.physics.primitives": "0.0.7", - "ngraph.quadtreebh": "0.0.4", - "ngraph.random": "0.0.1" - } - }, - "ngraph.quadtreebh": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/ngraph.quadtreebh/-/ngraph.quadtreebh-0.0.4.tgz", - "integrity": "sha1-xwDUTm5K8HttBQAbo5h/9eLc1iw=", - "requires": { - "ngraph.random": "0.0.1" - } - }, - "ngraph.random": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/ngraph.random/-/ngraph.random-0.0.1.tgz", - "integrity": "sha1-wAji67/f+vF+0Q5LvJE+VnFmvPg=" - }, - "ngraph.remove-overlaps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ngraph.remove-overlaps/-/ngraph.remove-overlaps-1.0.0.tgz", - "integrity": "sha1-tMBjVT6kzx/3gWjnt//2JhfA2fQ=", - "dev": true - }, - "ngraph.tojson": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ngraph.tojson/-/ngraph.tojson-0.1.3.tgz", - "integrity": "sha1-chUq8zBsABeXu3zJKTDpIbp76zo=" - }, - "nopt": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-2.2.1.tgz", - "integrity": "sha1-KqCbfRdoSHs7ianFqlIzW/8Lrqc=", - "dev": true, - "requires": { - "abbrev": "1.1.0" - } - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "1.0.2" - } - }, - "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", - "dev": true - }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "requires": { - "array-each": "1.0.1", - "array-slice": "1.0.0", - "for-own": "1.0.0", - "isobject": "3.0.1" - }, - "dependencies": { - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "1.0.2" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true, - "requires": { - "for-own": "0.1.5", - "is-extendable": "0.1.1" - } - }, - "object.pick": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.2.0.tgz", - "integrity": "sha1-tTkr7peC2m2ft9avr1OXefEjTCs=", - "dev": true, - "requires": { - "isobject": "2.1.0" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1.0.2" - } - }, - "onetime": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true - }, - "optimist": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", - "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=", - "dev": true, - "requires": { - "wordwrap": "0.0.3" - } - }, - "orchestrator": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", - "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", - "dev": true, - "requires": { - "end-of-stream": "0.1.5", - "sequencify": "0.0.7", - "stream-consume": "0.1.0" - } - }, - "ordered-read-streams": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", - "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", - "dev": true - }, - "os-browserify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.1.2.tgz", - "integrity": "sha1-ScoCk+CxlZCl9d4Qx/JlphfY/lQ=", - "dev": true - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "pako": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", - "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", - "dev": true - }, - "parents": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", - "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", - "dev": true, - "requires": { - "path-platform": "0.11.15" - } - }, - "parse-asn1": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", - "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", - "dev": true, - "requires": { - "asn1.js": "4.9.1", - "browserify-aes": "1.0.6", - "create-hash": "1.1.3", - "evp_bytestokey": "1.0.0", - "pbkdf2": "3.0.13" - } - }, - "parse-filepath": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.1.tgz", - "integrity": "sha1-FZ1hVdQ5BNFsEO9piRHaHpGWm3M=", - "dev": true, - "requires": { - "is-absolute": "0.2.6", - "map-cache": "0.2.2", - "path-root": "0.1.1" - } - }, - "parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "dev": true, - "requires": { - "glob-base": "0.3.0", - "is-dotfile": "1.0.3", - "is-extglob": "1.0.0", - "is-glob": "2.0.1" - } - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "path-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", - "dev": true - }, - "path-platform": { - "version": "0.11.15", - "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", - "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", - "dev": true - }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "requires": { - "path-root-regex": "0.1.2" - } - }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true - }, - "pbkdf2": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.13.tgz", - "integrity": "sha512-+dCHxDH+djNtjgWmvVC/my3SYBAKpKNqKSjLkp+GtWWYe4XPE+e/PSD2aCanlEZZnqPk2uekTKNC/ccbwd2X2Q==", - "dev": true, - "requires": { - "create-hash": "1.1.3", - "create-hmac": "1.1.6", - "ripemd160": "2.0.1", - "safe-buffer": "5.1.1", - "sha.js": "2.4.8" - } - }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true - }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true - }, - "process": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/process/-/process-0.10.1.tgz", - "integrity": "sha1-hCRXzFHP7XLcd1r+6vuMYDQ3JyU=", - "dev": true - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true - }, - "public-encrypt": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", - "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", - "dev": true, - "requires": { - "bn.js": "4.11.7", - "browserify-rsa": "4.0.1", - "create-hash": "1.1.3", - "parse-asn1": "5.1.0", - "randombytes": "2.0.5" - } - }, - "punycode": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.2.4.tgz", - "integrity": "sha1-VACKyXKux0F13vnLpt9/qdORh0A=", - "dev": true - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true - }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", - "dev": true - }, - "randomatic": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", - "dev": true, - "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.5" - } - } - } - }, - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "1.1.5" - } - } - } - }, - "randombytes": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz", - "integrity": "sha512-8T7Zn1AhMsQ/HI1SjcCfT/t4ii3eAqco3yOcSzS4mozsOz69lHLsoMXmF9nZgnFanYscnSlUSgs8uZyKzpE6kg==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "readable-wrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/readable-wrap/-/readable-wrap-1.0.0.tgz", - "integrity": "sha1-O1ohHGMeEjA6VJkcgGwX564ga/8=", - "dev": true, - "requires": { - "readable-stream": "1.1.14" - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "1.4.0" - }, - "dependencies": { - "resolve": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz", - "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", - "dev": true, - "requires": { - "path-parse": "1.0.5" - } - } - } - }, - "regex-cache": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz", - "integrity": "sha1-mxpsNdTQ3871cRrmUejp09cRQUU=", - "dev": true, - "requires": { - "is-equal-shallow": "0.1.3", - "is-primitive": "2.0.0" - } - }, - "remove-trailing-separator": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.0.2.tgz", - "integrity": "sha1-abBi2XhyetFNxrVrpKt3L9jXBRE=", - "dev": true - }, - "repeat-element": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "resolve": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.7.4.tgz", - "integrity": "sha1-OVqe+ehz+/4SvRRAi9kbuTYAPWk=", - "dev": true - }, - "resolve-dir": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", - "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=", - "dev": true, - "requires": { - "expand-tilde": "1.2.2", - "global-modules": "0.2.3" - } - }, - "rfile": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/rfile/-/rfile-1.0.0.tgz", - "integrity": "sha1-WXCM+Qyh50xUw8/Fw2/bmBBDUmE=", - "dev": true, - "requires": { - "callsite": "1.0.0", - "resolve": "0.3.1" - }, - "dependencies": { - "resolve": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.3.1.tgz", - "integrity": "sha1-NMY0R8ZkxwWY0cmxJvxDsqJDEKQ=", - "dev": true - } - } - }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, - "requires": { - "align-text": "0.1.4" - } - }, - "rimraf": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", - "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", - "dev": true, - "requires": { - "glob": "7.1.2" - }, - "dependencies": { - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "1.1.8" - } - } - } - }, - "ripemd160": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", - "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", - "dev": true, - "requires": { - "hash-base": "2.0.2", - "inherits": "2.0.3" - } - }, - "ruglify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ruglify/-/ruglify-1.0.0.tgz", - "integrity": "sha1-3Ikw4qlUSidDAcyZcldMDQmGtnU=", - "dev": true, - "requires": { - "rfile": "1.0.0", - "uglify-js": "2.2.5" - }, - "dependencies": { - "uglify-js": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.2.5.tgz", - "integrity": "sha1-puAqcNg5eSuXgEiLe4sYTAlcmcc=", - "dev": true, - "requires": { - "optimist": "0.3.7", - "source-map": "0.1.43" - } - } - } - }, - "runforcover": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/runforcover/-/runforcover-0.0.2.tgz", - "integrity": "sha1-NE8FfY1F0zrrxsyCIEZ49pxIV8w=", - "dev": true, - "requires": { - "bunker": "0.1.2" - } - }, - "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", - "dev": true - }, - "semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", - "dev": true - }, - "sequencify": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", - "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", - "dev": true - }, - "set-immediate-shim": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", - "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", - "dev": true - }, - "sha.js": { - "version": "2.4.8", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.8.tgz", - "integrity": "sha1-NwaMLEdra69ALRSknGf1l5IfY08=", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, - "shallow-copy": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", - "integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=", - "dev": true - }, - "shasum": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", - "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", - "dev": true, - "requires": { - "json-stable-stringify": "0.0.1", - "sha.js": "2.4.8" - } - }, - "shell-quote": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-0.0.1.tgz", - "integrity": "sha1-GkEZbzwDM8SCMjWT1ohuzxU92YY=", - "dev": true - }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", - "dev": true - }, - "simplesvg": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/simplesvg/-/simplesvg-0.0.10.tgz", - "integrity": "sha1-N9LsGN4sFU3Ztp956K0gvx4eX90=", - "requires": { - "add-event-listener": "0.0.1" - } - }, - "slide": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", - "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", - "dev": true - }, - "source-map": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", - "dev": true, - "requires": { - "amdefine": "1.0.1" - } - }, - "sparkles": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", - "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", - "dev": true - }, - "stream-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-1.0.0.tgz", - "integrity": "sha1-v5tKv7QrJ011FHnkTg/yZWtvEZM=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "1.1.14" - } - }, - "stream-combiner2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.0.2.tgz", - "integrity": "sha1-unKmtQy/q/qVD8i8h2BL0B62BnE=", - "dev": true, - "requires": { - "duplexer2": "0.0.2", - "through2": "0.5.1" - }, - "dependencies": { - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "through2": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", - "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "3.0.0" - } - } - } - }, - "stream-consume": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz", - "integrity": "sha1-pB6tGm1ggc63n2WwYZAbbY89HQ8=", - "dev": true - }, - "stream-splicer": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-1.3.2.tgz", - "integrity": "sha1-PARBvhW5v04iYnXm3IOWR0VUZmE=", - "dev": true, - "requires": { - "indexof": "0.0.1", - "inherits": "2.0.3", - "isarray": "0.0.1", - "readable-stream": "1.1.14", - "readable-wrap": "1.0.0", - "through2": "1.1.1" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "strip-bom": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", - "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", - "dev": true, - "requires": { - "first-chunk-stream": "1.0.0", - "is-utf8": "0.2.1" - } - }, - "subarg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", - "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", - "dev": true, - "requires": { - "minimist": "1.2.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "syntax-error": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.3.0.tgz", - "integrity": "sha1-HtkmbE1AvnXcVb+bsct3Biu5bKE=", - "dev": true, - "requires": { - "acorn": "4.0.13" - } - }, - "tap": { - "version": "0.4.13", - "resolved": "https://registry.npmjs.org/tap/-/tap-0.4.13.tgz", - "integrity": "sha1-OYYTTWdZcn/CIj5hEm7rhyQ6zLw=", - "dev": true, - "requires": { - "buffer-equal": "0.0.2", - "deep-equal": "0.0.0", - "difflet": "0.2.6", - "glob": "3.2.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "nopt": "2.2.1", - "runforcover": "0.0.2", - "slide": "1.1.6", - "yamlish": "0.0.7" - }, - "dependencies": { - "deep-equal": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.0.0.tgz", - "integrity": "sha1-mWedO70EcVb81FDT0B7rkGhpHoM=", - "dev": true - }, - "glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", - "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "minimatch": "0.3.0" - } - }, - "minimatch": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", - "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", - "dev": true, - "requires": { - "lru-cache": "2.7.3", - "sigmund": "1.0.1" - } - } - } - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "through2": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/through2/-/through2-1.1.1.tgz", - "integrity": "sha1-CEfLxESfNAVXTb3M2buEG4OsNUU=", - "dev": true, - "requires": { - "readable-stream": "1.1.14", - "xtend": "4.0.1" - }, - "dependencies": { - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - } - } - }, - "tildify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", - "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", - "dev": true, - "requires": { - "os-homedir": "1.0.2" - } - }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true - }, - "timers-browserify": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", - "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", - "dev": true, - "requires": { - "process": "0.11.10" - }, - "dependencies": { - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true - } - } - }, - "traverse": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", - "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=", - "dev": true - }, - "tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", - "dev": true - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "uglify-js": { - "version": "2.4.24", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.24.tgz", - "integrity": "sha1-+tV1XB4Vd2WLsG/5q25UjJW+vW4=", - "dev": true, - "requires": { - "async": "0.2.10", - "source-map": "0.1.34", - "uglify-to-browserify": "1.0.2", - "yargs": "3.5.4" - }, - "dependencies": { - "source-map": { - "version": "0.1.34", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.34.tgz", - "integrity": "sha1-p8/omux7FoLDsZjQrPtH19CQVms=", - "dev": true, - "requires": { - "amdefine": "1.0.1" - } - } - } - }, - "uglify-save-license": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/uglify-save-license/-/uglify-save-license-0.4.1.tgz", - "integrity": "sha1-lXJsF8xv0XHDYX479NjYKqjEzOE=", - "dev": true - }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true - }, - "umd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/umd/-/umd-2.1.0.tgz", - "integrity": "sha1-SmMHt2LxfwLSAbX6FU5nM5bCY88=", - "dev": true, - "requires": { - "rfile": "1.0.0", - "ruglify": "1.0.0", - "through": "2.3.8", - "uglify-js": "2.4.24" - } - }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true - }, - "unique-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", - "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", - "dev": true - }, - "url": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", - "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", - "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - }, - "user-home": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", - "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", - "dev": true - }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "requires": { - "inherits": "2.0.1" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - } - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "v8flags": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", - "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", - "dev": true, - "requires": { - "user-home": "1.1.1" - } - }, - "vinyl": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", - "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true, - "requires": { - "clone": "1.0.2", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - }, - "vinyl-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/vinyl-buffer/-/vinyl-buffer-1.0.0.tgz", - "integrity": "sha1-ygZ+oIQx1QdyKx3lCD9gJhbrwjQ=", - "dev": true, - "requires": { - "bl": "0.9.5", - "through2": "0.6.5" - }, - "dependencies": { - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - } - } - }, - "vinyl-fs": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", - "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", - "dev": true, - "requires": { - "defaults": "1.0.3", - "glob-stream": "3.1.18", - "glob-watcher": "0.0.6", - "graceful-fs": "3.0.11", - "mkdirp": "0.5.1", - "strip-bom": "1.0.0", - "through2": "0.6.5", - "vinyl": "0.4.6" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" - } - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - } - } - }, - "vinyl-source-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-1.1.0.tgz", - "integrity": "sha1-RMvlEIIFJ53rDFZTwJSiiHk4sas=", - "dev": true, - "requires": { - "through2": "0.6.5", - "vinyl": "0.4.6" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" - } - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - } - } - }, - "vinyl-sourcemaps-apply": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", - "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", - "dev": true, - "requires": { - "source-map": "0.5.6" - }, - "dependencies": { - "source-map": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", - "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", - "dev": true - } - } - }, - "vm-browserify": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", - "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", - "dev": true, - "requires": { - "indexof": "0.0.1" - } - }, - "which": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", - "dev": true, - "requires": { - "isexe": "2.0.0" - } - }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true - }, - "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "xtend": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", - "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", - "dev": true - }, - "yamlish": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/yamlish/-/yamlish-0.0.7.tgz", - "integrity": "sha1-tK+aHcxjYYhzw9bkUewyE8OaV/s=", - "dev": true - }, - "yargs": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.5.4.tgz", - "integrity": "sha1-2K/49mXpTDS9JZvevRv68N3TU2E=", - "dev": true, - "requires": { - "camelcase": "1.2.1", - "decamelize": "1.2.0", - "window-size": "0.1.0", - "wordwrap": "0.0.2" - }, - "dependencies": { - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true - } - } - } - } -} From c2d3837c386c445c378183470f795ea21e51053c Mon Sep 17 00:00:00 2001 From: Andriy Kashcha Date: Mon, 7 Aug 2017 22:33:15 -0700 Subject: [PATCH 240/276] Rebuild the library locally --- dist/vivagraph.js | 4062 ++++++++++++++++++++++----------------------- 1 file changed, 2031 insertions(+), 2031 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 0ecff26..4f0fad5 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -3252,42 +3252,42 @@ function fail() { } },{}],32:[function(require,module,exports){ -var centrality = require('ngraph.centrality'); - -module.exports = centralityWrapper; - -function centralityWrapper() { - // TODO: This should not be a function - return { - betweennessCentrality: betweennessCentrality, - degreeCentrality: degreeCentrality - }; -} - -function betweennessCentrality(g) { - var betweenness = centrality.betweenness(g); - return toVivaGraphCentralityFormat(betweenness); -} - -function degreeCentrality(g, kind) { - var degree = centrality.degree(g, kind); - return toVivaGraphCentralityFormat(degree); -} - -function toVivaGraphCentralityFormat(centrality) { - return Object.keys(centrality).sort(byValue).map(toKeyValue); - - function byValue(x, y) { - return centrality[y] - centrality[x]; - } - - function toKeyValue(key) { - return { - key: key, - value: centrality[key] - }; - } -} +var centrality = require('ngraph.centrality'); + +module.exports = centralityWrapper; + +function centralityWrapper() { + // TODO: This should not be a function + return { + betweennessCentrality: betweennessCentrality, + degreeCentrality: degreeCentrality + }; +} + +function betweennessCentrality(g) { + var betweenness = centrality.betweenness(g); + return toVivaGraphCentralityFormat(betweenness); +} + +function degreeCentrality(g, kind) { + var degree = centrality.degree(g, kind); + return toVivaGraphCentralityFormat(degree); +} + +function toVivaGraphCentralityFormat(centrality) { + return Object.keys(centrality).sort(byValue).map(toKeyValue); + + function byValue(x, y) { + return centrality[y] - centrality[x]; + } + + function toKeyValue(key) { + return { + key: key, + value: centrality[key] + }; + } +} },{"ngraph.centrality":4}],33:[function(require,module,exports){ /** @@ -3325,651 +3325,651 @@ function operations() { }; },{}],34:[function(require,module,exports){ -/** - * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka - */ - -module.exports = domInputManager; - -var dragndrop = require('./dragndrop.js'); - -function domInputManager(graph, graphics) { - var nodeEvents = {}; - return { - /** - * Called by renderer to listen to drag-n-drop events from node. E.g. for SVG - * graphics we may listen to DOM events, whereas for WebGL the graphics - * should provide custom eventing mechanism. - * - * @param node - to be monitored. - * @param handlers - object with set of three callbacks: - * onStart: function(), - * onDrag: function(e, offset), - * onStop: function() - */ - bindDragNDrop: bindDragNDrop - }; - - function bindDragNDrop(node, handlers) { - var events; - if (handlers) { - var nodeUI = graphics.getNodeUI(node.id); - events = dragndrop(nodeUI); - if (typeof handlers.onStart === 'function') { - events.onStart(handlers.onStart); - } - if (typeof handlers.onDrag === 'function') { - events.onDrag(handlers.onDrag); - } - if (typeof handlers.onStop === 'function') { - events.onStop(handlers.onStop); - } - - nodeEvents[node.id] = events; - } else if ((events = nodeEvents[node.id])) { - events.release(); - delete nodeEvents[node.id]; - } - } -} +/** + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka + */ + +module.exports = domInputManager; + +var dragndrop = require('./dragndrop.js'); + +function domInputManager(graph, graphics) { + var nodeEvents = {}; + return { + /** + * Called by renderer to listen to drag-n-drop events from node. E.g. for SVG + * graphics we may listen to DOM events, whereas for WebGL the graphics + * should provide custom eventing mechanism. + * + * @param node - to be monitored. + * @param handlers - object with set of three callbacks: + * onStart: function(), + * onDrag: function(e, offset), + * onStop: function() + */ + bindDragNDrop: bindDragNDrop + }; + + function bindDragNDrop(node, handlers) { + var events; + if (handlers) { + var nodeUI = graphics.getNodeUI(node.id); + events = dragndrop(nodeUI); + if (typeof handlers.onStart === 'function') { + events.onStart(handlers.onStart); + } + if (typeof handlers.onDrag === 'function') { + events.onDrag(handlers.onDrag); + } + if (typeof handlers.onStop === 'function') { + events.onStop(handlers.onStop); + } + + nodeEvents[node.id] = events; + } else if ((events = nodeEvents[node.id])) { + events.release(); + delete nodeEvents[node.id]; + } + } +} },{"./dragndrop.js":35}],35:[function(require,module,exports){ -/** - * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka - */ - -module.exports = dragndrop; - -var documentEvents = require('../Utils/documentEvents.js'); -var browserInfo = require('../Utils/browserInfo.js'); -var findElementPosition = require('../Utils/findElementPosition.js'); - -// TODO: Move to input namespace -// TODO: Methods should be extracted into the prototype. This class -// does not need to consume so much memory for every tracked element -function dragndrop(element) { - var start, - drag, - end, - scroll, - prevSelectStart, - prevDragStart, - - startX = 0, - startY = 0, - dragObject, - touchInProgress = false, - pinchZoomLength = 0, - - getMousePos = function (e) { - var posx = 0, - posy = 0; - - e = e || window.event; - - if (e.pageX || e.pageY) { - posx = e.pageX; - posy = e.pageY; - } else if (e.clientX || e.clientY) { - posx = e.clientX + window.document.body.scrollLeft + window.document.documentElement.scrollLeft; - posy = e.clientY + window.document.body.scrollTop + window.document.documentElement.scrollTop; - } - - return [posx, posy]; - }, - - move = function (e, clientX, clientY) { - if (drag) { - drag(e, {x : clientX - startX, y : clientY - startY }); - } - - startX = clientX; - startY = clientY; - }, - - stopPropagation = function (e) { - if (e.stopPropagation) { e.stopPropagation(); } else { e.cancelBubble = true; } - }, - preventDefault = function (e) { - if (e.preventDefault) { e.preventDefault(); } - }, - - handleDisabledEvent = function (e) { - stopPropagation(e); - return false; - }, - - handleMouseMove = function (e) { - e = e || window.event; - - move(e, e.clientX, e.clientY); - }, - - handleMouseDown = function (e) { - e = e || window.event; - if (touchInProgress) { - // modern browsers will fire mousedown for touch events too - // we do not want this, since touch is handled separately. - stopPropagation(e); - return false; - } - // for IE, left click == 1 - // for Firefox, left click == 0 - var isLeftButton = ((e.button === 1 && window.event !== null) || e.button === 0); - - if (isLeftButton) { - startX = e.clientX; - startY = e.clientY; - - // TODO: bump zIndex? - dragObject = e.target || e.srcElement; - - if (start) { start(e, {x: startX, y : startY}); } - - documentEvents.on('mousemove', handleMouseMove); - documentEvents.on('mouseup', handleMouseUp); - - - stopPropagation(e); - // TODO: What if event already there? Not bullet proof: - prevSelectStart = window.document.onselectstart; - prevDragStart = window.document.ondragstart; - - window.document.onselectstart = handleDisabledEvent; - dragObject.ondragstart = handleDisabledEvent; - - // prevent text selection (except IE) - return false; - } - }, - - handleMouseUp = function (e) { - e = e || window.event; - - documentEvents.off('mousemove', handleMouseMove); - documentEvents.off('mouseup', handleMouseUp); - - window.document.onselectstart = prevSelectStart; - dragObject.ondragstart = prevDragStart; - dragObject = null; - if (end) { end(e); } - }, - - handleMouseWheel = function (e) { - if (typeof scroll !== 'function') { - return; - } - - e = e || window.event; - if (e.preventDefault) { - e.preventDefault(); - } - - e.returnValue = false; - var delta, - mousePos = getMousePos(e), - elementOffset = findElementPosition(element), - relMousePos = { - x: mousePos[0] - elementOffset[0], - y: mousePos[1] - elementOffset[1] - }; - - if (e.wheelDelta) { - delta = e.wheelDelta / 360; // Chrome/Safari - } else { - delta = e.detail / -9; // Mozilla - } - - scroll(e, delta, relMousePos); - }, - - updateScrollEvents = function (scrollCallback) { - if (!scroll && scrollCallback) { - // client is interested in scrolling. Start listening to events: - if (browserInfo.browser === 'webkit') { - element.addEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari - } else { - element.addEventListener('DOMMouseScroll', handleMouseWheel, false); // Others - } - } else if (scroll && !scrollCallback) { - if (browserInfo.browser === 'webkit') { - element.removeEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari - } else { - element.removeEventListener('DOMMouseScroll', handleMouseWheel, false); // Others - } - } - - scroll = scrollCallback; - }, - - getPinchZoomLength = function(finger1, finger2) { - return (finger1.clientX - finger2.clientX) * (finger1.clientX - finger2.clientX) + - (finger1.clientY - finger2.clientY) * (finger1.clientY - finger2.clientY); - }, - - handleTouchMove = function (e) { - if (e.touches.length === 1) { - stopPropagation(e); - - var touch = e.touches[0]; - move(e, touch.clientX, touch.clientY); - } else if (e.touches.length === 2) { - // it's a zoom: - var currentPinchLength = getPinchZoomLength(e.touches[0], e.touches[1]); - var delta = 0; - if (currentPinchLength < pinchZoomLength) { - delta = -1; - } else if (currentPinchLength > pinchZoomLength) { - delta = 1; - } - scroll(e, delta, {x: e.touches[0].clientX, y: e.touches[0].clientY}); - pinchZoomLength = currentPinchLength; - stopPropagation(e); - preventDefault(e); - } - }, - - handleTouchEnd = function (e) { - touchInProgress = false; - documentEvents.off('touchmove', handleTouchMove); - documentEvents.off('touchend', handleTouchEnd); - documentEvents.off('touchcancel', handleTouchEnd); - dragObject = null; - if (end) { end(e); } - }, - - handleSignleFingerTouch = function (e, touch) { - stopPropagation(e); - preventDefault(e); - - startX = touch.clientX; - startY = touch.clientY; - - dragObject = e.target || e.srcElement; - - if (start) { start(e, {x: startX, y : startY}); } - // TODO: can I enter into the state when touch is in progress - // but it's still a single finger touch? - if (!touchInProgress) { - touchInProgress = true; - documentEvents.on('touchmove', handleTouchMove); - documentEvents.on('touchend', handleTouchEnd); - documentEvents.on('touchcancel', handleTouchEnd); - } - }, - - handleTouchStart = function (e) { - if (e.touches.length === 1) { - return handleSignleFingerTouch(e, e.touches[0]); - } else if (e.touches.length === 2) { - // handleTouchMove() will care about pinch zoom. - stopPropagation(e); - preventDefault(e); - - pinchZoomLength = getPinchZoomLength(e.touches[0], e.touches[1]); - - } - // don't care about the rest. - }; - - - element.addEventListener('mousedown', handleMouseDown); - element.addEventListener('touchstart', handleTouchStart); - - return { - onStart : function (callback) { - start = callback; - return this; - }, - - onDrag : function (callback) { - drag = callback; - return this; - }, - - onStop : function (callback) { - end = callback; - return this; - }, - - /** - * Occurs when mouse wheel event happens. callback = function(e, scrollDelta, scrollPoint); - */ - onScroll : function (callback) { - updateScrollEvents(callback); - return this; - }, - - release : function () { - // TODO: could be unsafe. We might wanna release dragObject, etc. - element.removeEventListener('mousedown', handleMouseDown); - element.removeEventListener('touchstart', handleTouchStart); - - documentEvents.off('mousemove', handleMouseMove); - documentEvents.off('mouseup', handleMouseUp); - documentEvents.off('touchmove', handleTouchMove); - documentEvents.off('touchend', handleTouchEnd); - documentEvents.off('touchcancel', handleTouchEnd); - - updateScrollEvents(null); - } - }; -} +/** + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka + */ -},{"../Utils/browserInfo.js":39,"../Utils/documentEvents.js":40,"../Utils/findElementPosition.js":41}],36:[function(require,module,exports){ -/** - * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka - */ - -module.exports = webglInputManager; - -var createInputEvents = require('../WebGL/webglInputEvents.js'); - -function webglInputManager(graph, graphics) { - var inputEvents = createInputEvents(graphics), - draggedNode = null, - internalHandlers = {}, - pos = {x : 0, y : 0}; - - inputEvents.mouseDown(function (node, e) { - draggedNode = node; - pos.x = e.clientX; - pos.y = e.clientY; - - inputEvents.mouseCapture(draggedNode); - - var handlers = internalHandlers[node.id]; - if (handlers && handlers.onStart) { - handlers.onStart(e, pos); - } - - return true; - }).mouseUp(function (node) { - inputEvents.releaseMouseCapture(draggedNode); - - draggedNode = null; - var handlers = internalHandlers[node.id]; - if (handlers && handlers.onStop) { - handlers.onStop(); - } - return true; - }).mouseMove(function (node, e) { - if (draggedNode) { - var handlers = internalHandlers[draggedNode.id]; - if (handlers && handlers.onDrag) { - handlers.onDrag(e, {x : e.clientX - pos.x, y : e.clientY - pos.y }); - } - - pos.x = e.clientX; - pos.y = e.clientY; - return true; - } - }); - - return { - /** - * Called by renderer to listen to drag-n-drop events from node. E.g. for SVG - * graphics we may listen to DOM events, whereas for WebGL we graphics - * should provide custom eventing mechanism. - * - * @param node - to be monitored. - * @param handlers - object with set of three callbacks: - * onStart: function(), - * onDrag: function(e, offset), - * onStop: function() - */ - bindDragNDrop : function (node, handlers) { - internalHandlers[node.id] = handlers; - if (!handlers) { - delete internalHandlers[node.id]; - } - } - }; -} +module.exports = dragndrop; + +var documentEvents = require('../Utils/documentEvents.js'); +var browserInfo = require('../Utils/browserInfo.js'); +var findElementPosition = require('../Utils/findElementPosition.js'); + +// TODO: Move to input namespace +// TODO: Methods should be extracted into the prototype. This class +// does not need to consume so much memory for every tracked element +function dragndrop(element) { + var start, + drag, + end, + scroll, + prevSelectStart, + prevDragStart, + + startX = 0, + startY = 0, + dragObject, + touchInProgress = false, + pinchZoomLength = 0, + + getMousePos = function (e) { + var posx = 0, + posy = 0; + + e = e || window.event; + + if (e.pageX || e.pageY) { + posx = e.pageX; + posy = e.pageY; + } else if (e.clientX || e.clientY) { + posx = e.clientX + window.document.body.scrollLeft + window.document.documentElement.scrollLeft; + posy = e.clientY + window.document.body.scrollTop + window.document.documentElement.scrollTop; + } -},{"../WebGL/webglInputEvents.js":57}],37:[function(require,module,exports){ -module.exports = constant; - -var merge = require('ngraph.merge'); -var random = require('ngraph.random').random; -var Rect = require('../Utils/rect.js'); - -/** - * Does not really perform any layouting algorithm but is compliant - * with renderer interface. Allowing clients to provide specific positioning - * callback and get static layout of the graph - * - * @param {Viva.Graph.graph} graph to layout - * @param {Object} userSettings - */ -function constant(graph, userSettings) { - userSettings = merge(userSettings, { - maxX : 1024, - maxY : 1024, - seed : 'Deterministic randomness made me do this' - }); - // This class simply follows API, it does not use some of the arguments: - /*jshint unused: false */ - var rand = random(userSettings.seed), - graphRect = new Rect(Number.MAX_VALUE, Number.MAX_VALUE, Number.MIN_VALUE, Number.MIN_VALUE), - layoutLinks = {}, - - placeNodeCallback = function (node) { - return { - x: rand.next(userSettings.maxX), - y: rand.next(userSettings.maxY) - }; - }, - - updateGraphRect = function (position, graphRect) { - if (position.x < graphRect.x1) { graphRect.x1 = position.x; } - if (position.x > graphRect.x2) { graphRect.x2 = position.x; } - if (position.y < graphRect.y1) { graphRect.y1 = position.y; } - if (position.y > graphRect.y2) { graphRect.y2 = position.y; } - }, - - layoutNodes = typeof Object.create === 'function' ? Object.create(null) : {}, - - ensureNodeInitialized = function (node) { - layoutNodes[node.id] = placeNodeCallback(node); - updateGraphRect(layoutNodes[node.id], graphRect); - }, - - updateNodePositions = function () { - if (graph.getNodesCount() === 0) { return; } - - graphRect.x1 = Number.MAX_VALUE; - graphRect.y1 = Number.MAX_VALUE; - graphRect.x2 = Number.MIN_VALUE; - graphRect.y2 = Number.MIN_VALUE; - - graph.forEachNode(ensureNodeInitialized); - }, - - ensureLinkInitialized = function (link) { - layoutLinks[link.id] = link; - }, - - onGraphChanged = function(changes) { - for (var i = 0; i < changes.length; ++i) { - var change = changes[i]; - if (change.node) { - if (change.changeType === 'add') { - ensureNodeInitialized(change.node); - } else { - delete layoutNodes[change.node.id]; - } - } if (change.link) { - if (change.changeType === 'add') { - ensureLinkInitialized(change.link); - } else { - delete layoutLinks[change.link.id]; - } - } - } - }; - - graph.forEachNode(ensureNodeInitialized); - graph.forEachLink(ensureLinkInitialized); - graph.on('changed', onGraphChanged); - - return { - /** - * Attempts to layout graph within given number of iterations. - * - * @param {integer} [iterationsCount] number of algorithm's iterations. - * The constant layout ignores this parameter. - */ - run : function (iterationsCount) { - this.step(); - }, - - /** - * One step of layout algorithm. - */ - step : function () { - updateNodePositions(); - - return true; // no need to continue. - }, - - /** - * Returns rectangle structure {x1, y1, x2, y2}, which represents - * current space occupied by graph. - */ - getGraphRect : function () { - return graphRect; - }, - - /** - * Request to release all resources - */ - dispose : function () { - graph.off('change', onGraphChanged); - }, - - /* - * Checks whether given node is pinned; all nodes in this layout are pinned. - */ - isNodePinned: function (node) { - return true; - }, - - /* - * Requests layout algorithm to pin/unpin node to its current position - * Pinned nodes should not be affected by layout algorithm and always - * remain at their position - */ - pinNode: function (node, isPinned) { - // noop - }, - - /* - * Gets position of a node by its id. If node was not seen by this - * layout algorithm undefined value is returned; - */ - getNodePosition: getNodePosition, - - /** - * Returns {from, to} position of a link. - */ - getLinkPosition: function (linkId) { - var link = layoutLinks[linkId]; - return { - from : getNodePosition(link.fromId), - to : getNodePosition(link.toId) - }; - }, - - /** - * Sets position of a node to a given coordinates - */ - setNodePosition: function (nodeId, x, y) { - var pos = layoutNodes[nodeId]; - if (pos) { - pos.x = x; - pos.y = y; - } - }, - - // Layout specific methods: - - /** - * Based on argument either update default node placement callback or - * attempts to place given node using current placement callback. - * Setting new node callback triggers position update for all nodes. - * - * @param {Object} newPlaceNodeCallbackOrNode - if it is a function then - * default node placement callback is replaced with new one. Node placement - * callback has a form of function (node) {}, and is expected to return an - * object with x and y properties set to numbers. - * - * Otherwise if it's not a function the argument is treated as graph node - * and current node placement callback will be used to place it. - */ - placeNode : function (newPlaceNodeCallbackOrNode) { - if (typeof newPlaceNodeCallbackOrNode === 'function') { - placeNodeCallback = newPlaceNodeCallbackOrNode; - updateNodePositions(); - return this; - } - - // it is not a request to update placeNodeCallback, trying to place - // a node using current callback: - return placeNodeCallback(newPlaceNodeCallbackOrNode); - } - - }; - - function getNodePosition(nodeId) { - return layoutNodes[nodeId]; - } -} + return [posx, posy]; + }, + + move = function (e, clientX, clientY) { + if (drag) { + drag(e, {x : clientX - startX, y : clientY - startY }); + } + + startX = clientX; + startY = clientY; + }, + + stopPropagation = function (e) { + if (e.stopPropagation) { e.stopPropagation(); } else { e.cancelBubble = true; } + }, + preventDefault = function (e) { + if (e.preventDefault) { e.preventDefault(); } + }, + + handleDisabledEvent = function (e) { + stopPropagation(e); + return false; + }, + + handleMouseMove = function (e) { + e = e || window.event; + + move(e, e.clientX, e.clientY); + }, + + handleMouseDown = function (e) { + e = e || window.event; + if (touchInProgress) { + // modern browsers will fire mousedown for touch events too + // we do not want this, since touch is handled separately. + stopPropagation(e); + return false; + } + // for IE, left click == 1 + // for Firefox, left click == 0 + var isLeftButton = ((e.button === 1 && window.event !== null) || e.button === 0); + + if (isLeftButton) { + startX = e.clientX; + startY = e.clientY; + + // TODO: bump zIndex? + dragObject = e.target || e.srcElement; + + if (start) { start(e, {x: startX, y : startY}); } + + documentEvents.on('mousemove', handleMouseMove); + documentEvents.on('mouseup', handleMouseUp); + + + stopPropagation(e); + // TODO: What if event already there? Not bullet proof: + prevSelectStart = window.document.onselectstart; + prevDragStart = window.document.ondragstart; + + window.document.onselectstart = handleDisabledEvent; + dragObject.ondragstart = handleDisabledEvent; + + // prevent text selection (except IE) + return false; + } + }, + + handleMouseUp = function (e) { + e = e || window.event; + + documentEvents.off('mousemove', handleMouseMove); + documentEvents.off('mouseup', handleMouseUp); + + window.document.onselectstart = prevSelectStart; + dragObject.ondragstart = prevDragStart; + dragObject = null; + if (end) { end(e); } + }, + + handleMouseWheel = function (e) { + if (typeof scroll !== 'function') { + return; + } + + e = e || window.event; + if (e.preventDefault) { + e.preventDefault(); + } + + e.returnValue = false; + var delta, + mousePos = getMousePos(e), + elementOffset = findElementPosition(element), + relMousePos = { + x: mousePos[0] - elementOffset[0], + y: mousePos[1] - elementOffset[1] + }; + + if (e.wheelDelta) { + delta = e.wheelDelta / 360; // Chrome/Safari + } else { + delta = e.detail / -9; // Mozilla + } + + scroll(e, delta, relMousePos); + }, + + updateScrollEvents = function (scrollCallback) { + if (!scroll && scrollCallback) { + // client is interested in scrolling. Start listening to events: + if (browserInfo.browser === 'webkit') { + element.addEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari + } else { + element.addEventListener('DOMMouseScroll', handleMouseWheel, false); // Others + } + } else if (scroll && !scrollCallback) { + if (browserInfo.browser === 'webkit') { + element.removeEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari + } else { + element.removeEventListener('DOMMouseScroll', handleMouseWheel, false); // Others + } + } + + scroll = scrollCallback; + }, + + getPinchZoomLength = function(finger1, finger2) { + return (finger1.clientX - finger2.clientX) * (finger1.clientX - finger2.clientX) + + (finger1.clientY - finger2.clientY) * (finger1.clientY - finger2.clientY); + }, + + handleTouchMove = function (e) { + if (e.touches.length === 1) { + stopPropagation(e); + + var touch = e.touches[0]; + move(e, touch.clientX, touch.clientY); + } else if (e.touches.length === 2) { + // it's a zoom: + var currentPinchLength = getPinchZoomLength(e.touches[0], e.touches[1]); + var delta = 0; + if (currentPinchLength < pinchZoomLength) { + delta = -1; + } else if (currentPinchLength > pinchZoomLength) { + delta = 1; + } + scroll(e, delta, {x: e.touches[0].clientX, y: e.touches[0].clientY}); + pinchZoomLength = currentPinchLength; + stopPropagation(e); + preventDefault(e); + } + }, + + handleTouchEnd = function (e) { + touchInProgress = false; + documentEvents.off('touchmove', handleTouchMove); + documentEvents.off('touchend', handleTouchEnd); + documentEvents.off('touchcancel', handleTouchEnd); + dragObject = null; + if (end) { end(e); } + }, + + handleSignleFingerTouch = function (e, touch) { + stopPropagation(e); + preventDefault(e); + + startX = touch.clientX; + startY = touch.clientY; + + dragObject = e.target || e.srcElement; + + if (start) { start(e, {x: startX, y : startY}); } + // TODO: can I enter into the state when touch is in progress + // but it's still a single finger touch? + if (!touchInProgress) { + touchInProgress = true; + documentEvents.on('touchmove', handleTouchMove); + documentEvents.on('touchend', handleTouchEnd); + documentEvents.on('touchcancel', handleTouchEnd); + } + }, + + handleTouchStart = function (e) { + if (e.touches.length === 1) { + return handleSignleFingerTouch(e, e.touches[0]); + } else if (e.touches.length === 2) { + // handleTouchMove() will care about pinch zoom. + stopPropagation(e); + preventDefault(e); + + pinchZoomLength = getPinchZoomLength(e.touches[0], e.touches[1]); + + } + // don't care about the rest. + }; + + + element.addEventListener('mousedown', handleMouseDown); + element.addEventListener('touchstart', handleTouchStart); + + return { + onStart : function (callback) { + start = callback; + return this; + }, + + onDrag : function (callback) { + drag = callback; + return this; + }, + + onStop : function (callback) { + end = callback; + return this; + }, + + /** + * Occurs when mouse wheel event happens. callback = function(e, scrollDelta, scrollPoint); + */ + onScroll : function (callback) { + updateScrollEvents(callback); + return this; + }, + + release : function () { + // TODO: could be unsafe. We might wanna release dragObject, etc. + element.removeEventListener('mousedown', handleMouseDown); + element.removeEventListener('touchstart', handleTouchStart); + + documentEvents.off('mousemove', handleMouseMove); + documentEvents.off('mouseup', handleMouseUp); + documentEvents.off('touchmove', handleTouchMove); + documentEvents.off('touchend', handleTouchEnd); + documentEvents.off('touchcancel', handleTouchEnd); + + updateScrollEvents(null); + } + }; +} + +},{"../Utils/browserInfo.js":39,"../Utils/documentEvents.js":40,"../Utils/findElementPosition.js":41}],36:[function(require,module,exports){ +/** + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka + */ + +module.exports = webglInputManager; + +var createInputEvents = require('../WebGL/webglInputEvents.js'); + +function webglInputManager(graph, graphics) { + var inputEvents = createInputEvents(graphics), + draggedNode = null, + internalHandlers = {}, + pos = {x : 0, y : 0}; + + inputEvents.mouseDown(function (node, e) { + draggedNode = node; + pos.x = e.clientX; + pos.y = e.clientY; + + inputEvents.mouseCapture(draggedNode); + + var handlers = internalHandlers[node.id]; + if (handlers && handlers.onStart) { + handlers.onStart(e, pos); + } + + return true; + }).mouseUp(function (node) { + inputEvents.releaseMouseCapture(draggedNode); + + draggedNode = null; + var handlers = internalHandlers[node.id]; + if (handlers && handlers.onStop) { + handlers.onStop(); + } + return true; + }).mouseMove(function (node, e) { + if (draggedNode) { + var handlers = internalHandlers[draggedNode.id]; + if (handlers && handlers.onDrag) { + handlers.onDrag(e, {x : e.clientX - pos.x, y : e.clientY - pos.y }); + } + + pos.x = e.clientX; + pos.y = e.clientY; + return true; + } + }); + + return { + /** + * Called by renderer to listen to drag-n-drop events from node. E.g. for SVG + * graphics we may listen to DOM events, whereas for WebGL we graphics + * should provide custom eventing mechanism. + * + * @param node - to be monitored. + * @param handlers - object with set of three callbacks: + * onStart: function(), + * onDrag: function(e, offset), + * onStop: function() + */ + bindDragNDrop : function (node, handlers) { + internalHandlers[node.id] = handlers; + if (!handlers) { + delete internalHandlers[node.id]; + } + } + }; +} + +},{"../WebGL/webglInputEvents.js":57}],37:[function(require,module,exports){ +module.exports = constant; + +var merge = require('ngraph.merge'); +var random = require('ngraph.random').random; +var Rect = require('../Utils/rect.js'); + +/** + * Does not really perform any layouting algorithm but is compliant + * with renderer interface. Allowing clients to provide specific positioning + * callback and get static layout of the graph + * + * @param {Viva.Graph.graph} graph to layout + * @param {Object} userSettings + */ +function constant(graph, userSettings) { + userSettings = merge(userSettings, { + maxX : 1024, + maxY : 1024, + seed : 'Deterministic randomness made me do this' + }); + // This class simply follows API, it does not use some of the arguments: + /*jshint unused: false */ + var rand = random(userSettings.seed), + graphRect = new Rect(Number.MAX_VALUE, Number.MAX_VALUE, Number.MIN_VALUE, Number.MIN_VALUE), + layoutLinks = {}, + + placeNodeCallback = function (node) { + return { + x: rand.next(userSettings.maxX), + y: rand.next(userSettings.maxY) + }; + }, + + updateGraphRect = function (position, graphRect) { + if (position.x < graphRect.x1) { graphRect.x1 = position.x; } + if (position.x > graphRect.x2) { graphRect.x2 = position.x; } + if (position.y < graphRect.y1) { graphRect.y1 = position.y; } + if (position.y > graphRect.y2) { graphRect.y2 = position.y; } + }, + + layoutNodes = typeof Object.create === 'function' ? Object.create(null) : {}, + + ensureNodeInitialized = function (node) { + layoutNodes[node.id] = placeNodeCallback(node); + updateGraphRect(layoutNodes[node.id], graphRect); + }, + + updateNodePositions = function () { + if (graph.getNodesCount() === 0) { return; } + + graphRect.x1 = Number.MAX_VALUE; + graphRect.y1 = Number.MAX_VALUE; + graphRect.x2 = Number.MIN_VALUE; + graphRect.y2 = Number.MIN_VALUE; + + graph.forEachNode(ensureNodeInitialized); + }, + + ensureLinkInitialized = function (link) { + layoutLinks[link.id] = link; + }, + + onGraphChanged = function(changes) { + for (var i = 0; i < changes.length; ++i) { + var change = changes[i]; + if (change.node) { + if (change.changeType === 'add') { + ensureNodeInitialized(change.node); + } else { + delete layoutNodes[change.node.id]; + } + } if (change.link) { + if (change.changeType === 'add') { + ensureLinkInitialized(change.link); + } else { + delete layoutLinks[change.link.id]; + } + } + } + }; + + graph.forEachNode(ensureNodeInitialized); + graph.forEachLink(ensureLinkInitialized); + graph.on('changed', onGraphChanged); + + return { + /** + * Attempts to layout graph within given number of iterations. + * + * @param {integer} [iterationsCount] number of algorithm's iterations. + * The constant layout ignores this parameter. + */ + run : function (iterationsCount) { + this.step(); + }, + + /** + * One step of layout algorithm. + */ + step : function () { + updateNodePositions(); + + return true; // no need to continue. + }, + + /** + * Returns rectangle structure {x1, y1, x2, y2}, which represents + * current space occupied by graph. + */ + getGraphRect : function () { + return graphRect; + }, + + /** + * Request to release all resources + */ + dispose : function () { + graph.off('change', onGraphChanged); + }, + + /* + * Checks whether given node is pinned; all nodes in this layout are pinned. + */ + isNodePinned: function (node) { + return true; + }, + + /* + * Requests layout algorithm to pin/unpin node to its current position + * Pinned nodes should not be affected by layout algorithm and always + * remain at their position + */ + pinNode: function (node, isPinned) { + // noop + }, + + /* + * Gets position of a node by its id. If node was not seen by this + * layout algorithm undefined value is returned; + */ + getNodePosition: getNodePosition, + + /** + * Returns {from, to} position of a link. + */ + getLinkPosition: function (linkId) { + var link = layoutLinks[linkId]; + return { + from : getNodePosition(link.fromId), + to : getNodePosition(link.toId) + }; + }, + + /** + * Sets position of a node to a given coordinates + */ + setNodePosition: function (nodeId, x, y) { + var pos = layoutNodes[nodeId]; + if (pos) { + pos.x = x; + pos.y = y; + } + }, + + // Layout specific methods: + + /** + * Based on argument either update default node placement callback or + * attempts to place given node using current placement callback. + * Setting new node callback triggers position update for all nodes. + * + * @param {Object} newPlaceNodeCallbackOrNode - if it is a function then + * default node placement callback is replaced with new one. Node placement + * callback has a form of function (node) {}, and is expected to return an + * object with x and y properties set to numbers. + * + * Otherwise if it's not a function the argument is treated as graph node + * and current node placement callback will be used to place it. + */ + placeNode : function (newPlaceNodeCallbackOrNode) { + if (typeof newPlaceNodeCallbackOrNode === 'function') { + placeNodeCallback = newPlaceNodeCallbackOrNode; + updateNodePositions(); + return this; + } + + // it is not a request to update placeNodeCallback, trying to place + // a node using current callback: + return placeNodeCallback(newPlaceNodeCallbackOrNode); + } + + }; + + function getNodePosition(nodeId) { + return layoutNodes[nodeId]; + } +} },{"../Utils/rect.js":45,"ngraph.merge":13,"ngraph.random":26}],38:[function(require,module,exports){ -/** - * This module provides compatibility layer with 0.6.x library. It will be - * removed in the next version - */ - -var events = require('ngraph.events'); - -module.exports = backwardCompatibleEvents; - -function backwardCompatibleEvents(g) { - console.log("This method is deprecated. Please use Viva.events() instead"); - - if (!g) { - return g; - } - - var eventsDefined = (g.on !== undefined) || - (g.off !== undefined) || - (g.fire !== undefined); - - if (eventsDefined) { - // events already defined, ignore - return { - extend: function() { - return g; - }, - on: g.on, - stop: g.off - }; - } - - return { - extend: extend, - on: g.on, - stop: g.off - }; - - function extend() { - var backwardCompatible = events(g); - backwardCompatible.addEventListener = backwardCompatible.on; - return backwardCompatible; - } -} +/** + * This module provides compatibility layer with 0.6.x library. It will be + * removed in the next version + */ + +var events = require('ngraph.events'); + +module.exports = backwardCompatibleEvents; + +function backwardCompatibleEvents(g) { + console.log("This method is deprecated. Please use Viva.events() instead"); + + if (!g) { + return g; + } + + var eventsDefined = (g.on !== undefined) || + (g.off !== undefined) || + (g.fire !== undefined); + + if (eventsDefined) { + // events already defined, ignore + return { + extend: function() { + return g; + }, + on: g.on, + stop: g.off + }; + } + + return { + extend: extend, + on: g.on, + stop: g.off + }; + + function extend() { + var backwardCompatible = events(g); + backwardCompatible.addEventListener = backwardCompatible.on; + return backwardCompatible; + } +} },{"ngraph.events":7}],39:[function(require,module,exports){ module.exports = browserInfo(); @@ -4001,52 +4001,52 @@ function browserInfo() { } },{}],40:[function(require,module,exports){ -var nullEvents = require('./nullEvents.js'); - -module.exports = createDocumentEvents(); - -function createDocumentEvents() { - if (typeof document === undefined) { - return nullEvents; - } - - return { - on: on, - off: off - }; -} - -function on(eventName, handler) { - document.addEventListener(eventName, handler); -} - -function off(eventName, handler) { - document.removeEventListener(eventName, handler); -} +var nullEvents = require('./nullEvents.js'); -},{"./nullEvents.js":44}],41:[function(require,module,exports){ -/** - * Finds the absolute position of an element on a page - */ -module.exports = findElementPosition; - -function findElementPosition(obj) { - var curleft = 0, - curtop = 0; - if (obj.offsetParent) { - do { - curleft += obj.offsetLeft; - curtop += obj.offsetTop; - } while ((obj = obj.offsetParent) !== null); - } - - return [curleft, curtop]; -} +module.exports = createDocumentEvents(); -},{}],42:[function(require,module,exports){ -module.exports = getDimension; - -function getDimension(container) { +function createDocumentEvents() { + if (typeof document === undefined) { + return nullEvents; + } + + return { + on: on, + off: off + }; +} + +function on(eventName, handler) { + document.addEventListener(eventName, handler); +} + +function off(eventName, handler) { + document.removeEventListener(eventName, handler); +} + +},{"./nullEvents.js":44}],41:[function(require,module,exports){ +/** + * Finds the absolute position of an element on a page + */ +module.exports = findElementPosition; + +function findElementPosition(obj) { + var curleft = 0, + curtop = 0; + if (obj.offsetParent) { + do { + curleft += obj.offsetLeft; + curtop += obj.offsetTop; + } while ((obj = obj.offsetParent) !== null); + } + + return [curleft, curtop]; +} + +},{}],42:[function(require,module,exports){ +module.exports = getDimension; + +function getDimension(container) { if (!container) { throw { message : 'Cannot get dimensions of undefined container' @@ -4066,42 +4066,42 @@ function getDimension(container) { } },{}],43:[function(require,module,exports){ -var intersect = require('gintersect'); - -module.exports = intersectRect; - -function intersectRect(left, top, right, bottom, x1, y1, x2, y2) { - return intersect(left, top, left, bottom, x1, y1, x2, y2) || - intersect(left, bottom, right, bottom, x1, y1, x2, y2) || - intersect(right, bottom, right, top, x1, y1, x2, y2) || - intersect(right, top, left, top, x1, y1, x2, y2); -} +var intersect = require('gintersect'); + +module.exports = intersectRect; + +function intersectRect(left, top, right, bottom, x1, y1, x2, y2) { + return intersect(left, top, left, bottom, x1, y1, x2, y2) || + intersect(left, bottom, right, bottom, x1, y1, x2, y2) || + intersect(right, bottom, right, top, x1, y1, x2, y2) || + intersect(right, top, left, top, x1, y1, x2, y2); +} },{"gintersect":3}],44:[function(require,module,exports){ -module.exports = createNullEvents(); - -function createNullEvents() { - return { - on: noop, - off: noop, - stop: noop - }; -} - -function noop() { } +module.exports = createNullEvents(); + +function createNullEvents() { + return { + on: noop, + off: noop, + stop: noop + }; +} + +function noop() { } },{}],45:[function(require,module,exports){ -module.exports = Rect; - -/** - * Very generic rectangle. - */ -function Rect (x1, y1, x2, y2) { - this.x1 = x1 || 0; - this.y1 = y1 || 0; - this.x2 = x2 || 0; - this.y2 = y2 || 0; -} +module.exports = Rect; + +/** + * Very generic rectangle. + */ +function Rect (x1, y1, x2, y2) { + this.x1 = x1 || 0; + this.y1 = y1 || 0; + this.x2 = x2 || 0; + this.y2 = y2 || 0; +} },{}],46:[function(require,module,exports){ (function (global){ @@ -4200,29 +4200,29 @@ function noop() {} }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{}],47:[function(require,module,exports){ -var nullEvents = require('./nullEvents.js'); - -module.exports = createDocumentEvents(); - -function createDocumentEvents() { - if (typeof window === 'undefined') { - return nullEvents; - } - - return { - on: on, - off: off - }; -} - -function on(eventName, handler) { - window.addEventListener(eventName, handler); -} - -function off(eventName, handler) { - window.removeEventListener(eventName, handler); -} - +var nullEvents = require('./nullEvents.js'); + +module.exports = createDocumentEvents(); + +function createDocumentEvents() { + if (typeof window === 'undefined') { + return nullEvents; + } + + return { + on: on, + off: off + }; +} + +function on(eventName, handler) { + window.addEventListener(eventName, handler); +} + +function off(eventName, handler) { + window.removeEventListener(eventName, handler); +} + },{"./nullEvents.js":44}],48:[function(require,module,exports){ /** @@ -5652,1282 +5652,1282 @@ function webglGraphics(options) { } },{"../Input/webglInputManager.js":36,"../WebGL/webglLine.js":58,"../WebGL/webglLinkProgram.js":59,"../WebGL/webglNodeProgram.js":60,"../WebGL/webglSquare.js":61,"ngraph.events":7,"ngraph.merge":13}],51:[function(require,module,exports){ -module.exports = parseColor; - -function parseColor(color) { - var parsedColor = 0x009ee8ff; - - if (typeof color === 'string' && color) { - if (color.length === 4) { // #rgb - color = color.replace(/([^#])/g, '$1$1'); // duplicate each letter except first #. - } - if (color.length === 9) { // #rrggbbaa - parsedColor = parseInt(color.substr(1), 16); - } else if (color.length === 7) { // or #rrggbb. - parsedColor = (parseInt(color.substr(1), 16) << 8) | 0xff; - } else { - throw 'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: ' + color; - } - } else if (typeof color === 'number') { - parsedColor = color; - } - - return parsedColor; -} +module.exports = parseColor; + +function parseColor(color) { + var parsedColor = 0x009ee8ff; + + if (typeof color === 'string' && color) { + if (color.length === 4) { // #rgb + color = color.replace(/([^#])/g, '$1$1'); // duplicate each letter except first #. + } + if (color.length === 9) { // #rrggbbaa + parsedColor = parseInt(color.substr(1), 16); + } else if (color.length === 7) { // or #rrggbb. + parsedColor = (parseInt(color.substr(1), 16) << 8) | 0xff; + } else { + throw 'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: ' + color; + } + } else if (typeof color === 'number') { + parsedColor = color; + } + + return parsedColor; +} },{}],52:[function(require,module,exports){ -module.exports = Texture; - -/** - * Single texture in the webglAtlas. - */ -function Texture(size) { - this.canvas = window.document.createElement("canvas"); - this.ctx = this.canvas.getContext("2d"); - this.isDirty = false; - this.canvas.width = this.canvas.height = size; -} +module.exports = Texture; + +/** + * Single texture in the webglAtlas. + */ +function Texture(size) { + this.canvas = window.document.createElement("canvas"); + this.ctx = this.canvas.getContext("2d"); + this.isDirty = false; + this.canvas.width = this.canvas.height = size; +} },{}],53:[function(require,module,exports){ -/** - * @fileOverview Utility functions for webgl rendering. - * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com - */ - -module.exports = webgl; - -function webgl(gl) { - - return { - createProgram: createProgram, - extendArray: extendArray, - copyArrayPart: copyArrayPart, - swapArrayPart: swapArrayPart, - getLocations: getLocations, - context: gl - }; - - function createShader(shaderText, type) { - var shader = gl.createShader(type); - gl.shaderSource(shader, shaderText); - gl.compileShader(shader); - - if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { - var msg = gl.getShaderInfoLog(shader); - window.alert(msg); - throw msg; - } - - return shader; - } - - function createProgram(vertexShaderSrc, fragmentShaderSrc) { - var program = gl.createProgram(); - var vs = createShader(vertexShaderSrc, gl.VERTEX_SHADER); - var fs = createShader(fragmentShaderSrc, gl.FRAGMENT_SHADER); - - gl.attachShader(program, vs); - gl.attachShader(program, fs); - gl.linkProgram(program); - - if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { - var msg = gl.getShaderInfoLog(program); - window.alert(msg); - throw msg; - } - - return program; - } - - function extendArray(buffer, itemsInBuffer, elementsPerItem) { - if ((itemsInBuffer + 1) * elementsPerItem > buffer.length) { - // Every time we run out of space create new array twice bigger. - // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs - var extendedArray = new Float32Array(buffer.length * elementsPerItem * 2); - extendedArray.set(buffer); - - return extendedArray; - } - - return buffer; - } - - function getLocations(program, uniformOrAttributeNames) { - var foundLocations = {}; - for (var i = 0; i < uniformOrAttributeNames.length; ++i) { - var name = uniformOrAttributeNames[i]; - var location = -1; - if (name[0] === 'a' && name[1] === '_') { - location = gl.getAttribLocation(program, name); - if (location === -1) { - throw new Error("Program doesn't have required attribute: " + name); - } - - foundLocations[name.slice(2)] = location; - } else if (name[0] === 'u' && name[1] === '_') { - location = gl.getUniformLocation(program, name); - if (location === null) { - throw new Error("Program doesn't have required uniform: " + name); - } - - foundLocations[name.slice(2)] = location; - } else { - throw new Error("Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'"); - } - } - - return foundLocations; - } -} - -function copyArrayPart(array, to, from, elementsCount) { - for (var i = 0; i < elementsCount; ++i) { - array[to + i] = array[from + i]; - } -} - -function swapArrayPart(array, from, to, elementsCount) { - for (var i = 0; i < elementsCount; ++i) { - var tmp = array[from + i]; - array[from + i] = array[to + i]; - array[to + i] = tmp; - } -} +/** + * @fileOverview Utility functions for webgl rendering. + * + * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + */ -},{}],54:[function(require,module,exports){ -var Texture = require('./texture.js'); - -module.exports = webglAtlas; - -/** - * My naive implementation of textures atlas. It allows clients to load - * multiple images into atlas and get canvas representing all of them. - * - * @param tilesPerTexture - indicates how many images can be loaded to one - * texture of the atlas. If number of loaded images exceeds this - * parameter a new canvas will be created. - */ -function webglAtlas(tilesPerTexture) { - var tilesPerRow = Math.sqrt(tilesPerTexture || 1024) << 0, - tileSize = tilesPerRow, - lastLoadedIdx = 1, - loadedImages = {}, - dirtyTimeoutId, - skipedDirty = 0, - textures = [], - trackedUrls = []; - - if (!isPowerOf2(tilesPerTexture)) { - throw "Tiles per texture should be power of two."; - } - - // this is the return object - var api = { - /** - * indicates whether atlas has changed texture in it. If true then - * some of the textures has isDirty flag set as well. - */ - isDirty: false, - - /** - * Clears any signs of atlas changes. - */ - clearDirty: clearDirty, - - /** - * Removes given url from collection of tiles in the atlas. - */ - remove: remove, - - /** - * Gets all textures in the atlas. - */ - getTextures: getTextures, - - /** - * Gets coordinates of the given image in the atlas. Coordinates is an object: - * {offset : int } - where offset is an absolute position of the image in the - * atlas. - * - * Absolute means it can be larger than tilesPerTexture parameter, and in that - * case clients should get next texture in getTextures() collection. - */ - getCoordinates: getCoordinates, - - /** - * Asynchronously Loads the image to the atlas. Cross-domain security - * limitation applies. - */ - load: load - }; - - return api; - - function clearDirty() { - var i; - api.isDirty = false; - for (i = 0; i < textures.length; ++i) { - textures[i].isDirty = false; - } - } - - function remove(imgUrl) { - var coordinates = loadedImages[imgUrl]; - if (!coordinates) { - return false; - } - delete loadedImages[imgUrl]; - lastLoadedIdx -= 1; - - - if (lastLoadedIdx === coordinates.offset) { - return true; // Ignore if it's last image in the whole set. - } - - var tileToRemove = getTileCoordinates(coordinates.offset), - lastTileInSet = getTileCoordinates(lastLoadedIdx); - - copy(lastTileInSet, tileToRemove); - - var replacedOffset = loadedImages[trackedUrls[lastLoadedIdx]]; - replacedOffset.offset = coordinates.offset; - trackedUrls[coordinates.offset] = trackedUrls[lastLoadedIdx]; - - markDirty(); - return true; - } - - function getTextures() { - return textures; // I trust you... - } - - function getCoordinates(imgUrl) { - return loadedImages[imgUrl]; - } - - function load(imgUrl, callback) { - if (loadedImages.hasOwnProperty(imgUrl)) { - callback(loadedImages[imgUrl]); - } else { - var img = new window.Image(), - imgId = lastLoadedIdx; - - lastLoadedIdx += 1; - img.crossOrigin = "anonymous"; - img.onload = function() { - markDirty(); - drawAt(imgId, img, callback); - }; - - img.src = imgUrl; - } - } - - function createTexture() { - var texture = new Texture(tilesPerRow * tileSize); - textures.push(texture); - } - - function drawAt(tileNumber, img, callback) { - var tilePosition = getTileCoordinates(tileNumber), - coordinates = { - offset: tileNumber - }; - - if (tilePosition.textureNumber >= textures.length) { - createTexture(); - } - var currentTexture = textures[tilePosition.textureNumber]; - - currentTexture.ctx.drawImage(img, tilePosition.col * tileSize, tilePosition.row * tileSize, tileSize, tileSize); - trackedUrls[tileNumber] = img.src; - - loadedImages[img.src] = coordinates; - currentTexture.isDirty = true; - - callback(coordinates); - } - - function getTileCoordinates(absolutePosition) { - var textureNumber = (absolutePosition / tilesPerTexture) << 0, - localTileNumber = (absolutePosition % tilesPerTexture), - row = (localTileNumber / tilesPerRow) << 0, - col = (localTileNumber % tilesPerRow); - - return { - textureNumber: textureNumber, - row: row, - col: col - }; - } - - function markDirtyNow() { - api.isDirty = true; - skipedDirty = 0; - dirtyTimeoutId = null; - } - - function markDirty() { - // delay this call, since it results in texture reload - if (dirtyTimeoutId) { - window.clearTimeout(dirtyTimeoutId); - skipedDirty += 1; - dirtyTimeoutId = null; - } - - if (skipedDirty > 10) { - markDirtyNow(); - } else { - dirtyTimeoutId = window.setTimeout(markDirtyNow, 400); - } - } - - function copy(from, to) { - var fromCanvas = textures[from.textureNumber].canvas, - toCtx = textures[to.textureNumber].ctx, - x = to.col * tileSize, - y = to.row * tileSize; - - toCtx.drawImage(fromCanvas, from.col * tileSize, from.row * tileSize, tileSize, tileSize, x, y, tileSize, tileSize); - textures[from.textureNumber].isDirty = true; - textures[to.textureNumber].isDirty = true; - } -} - -function isPowerOf2(n) { - return (n & (n - 1)) === 0; -} +module.exports = webgl; -},{"./texture.js":52}],55:[function(require,module,exports){ -module.exports = webglImage; - -/** - * Represents a model for image. - */ -function webglImage(size, src) { - return { - /** - * Gets texture index where current image is placed. - */ - _texture : 0, - - /** - * Gets offset in the texture where current image is placed. - */ - _offset : 0, - - /** - * Gets size of the square with the image. - */ - size : typeof size === 'number' ? size : 32, - - /** - * Source of the image. If image is coming not from your domain - * certain origin restrictions applies. - * See http://www.khronos.org/registry/webgl/specs/latest/#4.2 for more details. - */ - src : src - }; -} +function webgl(gl) { -},{}],56:[function(require,module,exports){ -/** - * @fileOverview Defines an image nodes for webglGraphics class. - * Shape of nodes is square. - * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com - */ - -var WebglAtlas = require('./webglAtlas.js'); -var glUtils = require('./webgl.js'); - -module.exports = webglImageNodeProgram; - -/** - * Defines simple UI for nodes in webgl renderer. Each node is rendered as an image. - */ -function webglImageNodeProgram() { - // WebGL is gian state machine, we store some properties of the state here: - var ATTRIBUTES_PER_PRIMITIVE = 18; - var nodesFS = createNodeFragmentShader(); - var nodesVS = createNodeVertexShader(); - var tilesPerTexture = 1024; // TODO: Get based on max texture size - var atlas; - var program; - var gl; - var buffer; - var utils; - var locations; - var nodesCount = 0; - var nodes = new Float32Array(64); - var width; - var height; - var transform; - var sizeDirty; - - - return { - load: load, - - /** - * Updates position of current node in the buffer of nodes. - * - * @param idx - index of current node. - * @param pos - new position of the node. - */ - position: position, - - createNode: createNode, - - removeNode: removeNode, - - replaceProperties: replaceProperties, - - updateTransform: updateTransform, - - updateSize: updateSize, - - render: render - }; - - function refreshTexture(texture, idx) { - if (texture.nativeObject) { - gl.deleteTexture(texture.nativeObject); - } - - var nativeObject = gl.createTexture(); - gl.activeTexture(gl["TEXTURE" + idx]); - gl.bindTexture(gl.TEXTURE_2D, nativeObject); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.canvas); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST); - - gl.generateMipmap(gl.TEXTURE_2D); - gl.uniform1i(locations["sampler" + idx], idx); - - texture.nativeObject = nativeObject; - } - - function ensureAtlasTextureUpdated() { - if (atlas.isDirty) { - var textures = atlas.getTextures(), - i; - for (i = 0; i < textures.length; ++i) { - if (textures[i].isDirty || !textures[i].nativeObject) { - refreshTexture(textures[i], i); - } - } - - atlas.clearDirty(); - } - } - - function load(glContext) { - gl = glContext; - utils = glUtils(glContext); - - atlas = new WebglAtlas(tilesPerTexture); - - program = utils.createProgram(nodesVS, nodesFS); - gl.useProgram(program); - locations = utils.getLocations(program, ["a_vertexPos", "a_customAttributes", "u_screenSize", "u_transform", "u_sampler0", "u_sampler1", "u_sampler2", "u_sampler3", "u_tilesPerTexture"]); - - gl.uniform1f(locations.tilesPerTexture, tilesPerTexture); - - gl.enableVertexAttribArray(locations.vertexPos); - gl.enableVertexAttribArray(locations.customAttributes); - - buffer = gl.createBuffer(); - } - - function position(nodeUI, pos) { - var idx = nodeUI.id * ATTRIBUTES_PER_PRIMITIVE; - nodes[idx] = pos.x - nodeUI.size; - nodes[idx + 1] = pos.y - nodeUI.size; - nodes[idx + 2] = nodeUI._offset * 4; - - nodes[idx + 3] = pos.x + nodeUI.size; - nodes[idx + 4] = pos.y - nodeUI.size; - nodes[idx + 5] = nodeUI._offset * 4 + 1; - - nodes[idx + 6] = pos.x - nodeUI.size; - nodes[idx + 7] = pos.y + nodeUI.size; - nodes[idx + 8] = nodeUI._offset * 4 + 2; - - nodes[idx + 9] = pos.x - nodeUI.size; - nodes[idx + 10] = pos.y + nodeUI.size; - nodes[idx + 11] = nodeUI._offset * 4 + 2; - - nodes[idx + 12] = pos.x + nodeUI.size; - nodes[idx + 13] = pos.y - nodeUI.size; - nodes[idx + 14] = nodeUI._offset * 4 + 1; - - nodes[idx + 15] = pos.x + nodeUI.size; - nodes[idx + 16] = pos.y + nodeUI.size; - nodes[idx + 17] = nodeUI._offset * 4 + 3; - } - - function createNode(ui) { - nodes = utils.extendArray(nodes, nodesCount, ATTRIBUTES_PER_PRIMITIVE); - nodesCount += 1; - - var coordinates = atlas.getCoordinates(ui.src); - if (coordinates) { - ui._offset = coordinates.offset; - } else { - ui._offset = 0; - // Image is not yet loaded into the atlas. Reload it: - atlas.load(ui.src, function(coordinates) { - ui._offset = coordinates.offset; - }); - } - } - - function removeNode(nodeUI) { - if (nodesCount > 0) { - nodesCount -= 1; - } - - if (nodeUI.id < nodesCount && nodesCount > 0) { - if (nodeUI.src) { - atlas.remove(nodeUI.src); - } - - utils.copyArrayPart(nodes, nodeUI.id * ATTRIBUTES_PER_PRIMITIVE, nodesCount * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); - } - } - - function replaceProperties(replacedNode, newNode) { - newNode._offset = replacedNode._offset; - } - - function updateTransform(newTransform) { - sizeDirty = true; - transform = newTransform; - } - - function updateSize(w, h) { - width = w; - height = h; - sizeDirty = true; - } - - function render() { - gl.useProgram(program); - gl.bindBuffer(gl.ARRAY_BUFFER, buffer); - gl.bufferData(gl.ARRAY_BUFFER, nodes, gl.DYNAMIC_DRAW); - - if (sizeDirty) { - sizeDirty = false; - gl.uniformMatrix4fv(locations.transform, false, transform); - gl.uniform2f(locations.screenSize, width, height); - } - - gl.vertexAttribPointer(locations.vertexPos, 2, gl.FLOAT, false, 3 * Float32Array.BYTES_PER_ELEMENT, 0); - gl.vertexAttribPointer(locations.customAttributes, 1, gl.FLOAT, false, 3 * Float32Array.BYTES_PER_ELEMENT, 2 * 4); - - ensureAtlasTextureUpdated(); - - gl.drawArrays(gl.TRIANGLES, 0, nodesCount * 6); - } -} - -// TODO: Use glslify for shaders -function createNodeFragmentShader() { - return [ - "precision mediump float;", - "varying vec4 color;", - "varying vec3 vTextureCoord;", - "uniform sampler2D u_sampler0;", - "uniform sampler2D u_sampler1;", - "uniform sampler2D u_sampler2;", - "uniform sampler2D u_sampler3;", - - "void main(void) {", - " if (vTextureCoord.z == 0.) {", - " gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);", - " } else if (vTextureCoord.z == 1.) {", - " gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);", - " } else if (vTextureCoord.z == 2.) {", - " gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);", - " } else if (vTextureCoord.z == 3.) {", - " gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);", - " } else { gl_FragColor = vec4(0, 1, 0, 1); }", - "}" - ].join("\n"); -} - -function createNodeVertexShader() { - return [ - "attribute vec2 a_vertexPos;", - - "attribute float a_customAttributes;", - "uniform vec2 u_screenSize;", - "uniform mat4 u_transform;", - "uniform float u_tilesPerTexture;", - "varying vec3 vTextureCoord;", - - "void main(void) {", - " gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);", - "float corner = mod(a_customAttributes, 4.);", - "float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);", - "float tilesPerRow = sqrt(u_tilesPerTexture);", - "float tileSize = 1./tilesPerRow;", - "float tileColumn = mod(tileIndex, tilesPerRow);", - "float tileRow = floor(tileIndex/tilesPerRow);", - - "if(corner == 0.0) {", - " vTextureCoord.xy = vec2(0, 1);", - "} else if(corner == 1.0) {", - " vTextureCoord.xy = vec2(1, 1);", - "} else if(corner == 2.0) {", - " vTextureCoord.xy = vec2(0, 0);", - "} else {", - " vTextureCoord.xy = vec2(1, 0);", - "}", - - "vTextureCoord *= tileSize;", - "vTextureCoord.x += tileColumn * tileSize;", - "vTextureCoord.y += tileRow * tileSize;", - "vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);", - "}" - ].join("\n"); -} + return { + createProgram: createProgram, + extendArray: extendArray, + copyArrayPart: copyArrayPart, + swapArrayPart: swapArrayPart, + getLocations: getLocations, + context: gl + }; + + function createShader(shaderText, type) { + var shader = gl.createShader(type); + gl.shaderSource(shader, shaderText); + gl.compileShader(shader); + + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + var msg = gl.getShaderInfoLog(shader); + window.alert(msg); + throw msg; + } + + return shader; + } + + function createProgram(vertexShaderSrc, fragmentShaderSrc) { + var program = gl.createProgram(); + var vs = createShader(vertexShaderSrc, gl.VERTEX_SHADER); + var fs = createShader(fragmentShaderSrc, gl.FRAGMENT_SHADER); + + gl.attachShader(program, vs); + gl.attachShader(program, fs); + gl.linkProgram(program); + + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { + var msg = gl.getShaderInfoLog(program); + window.alert(msg); + throw msg; + } + + return program; + } + + function extendArray(buffer, itemsInBuffer, elementsPerItem) { + if ((itemsInBuffer + 1) * elementsPerItem > buffer.length) { + // Every time we run out of space create new array twice bigger. + // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs + var extendedArray = new Float32Array(buffer.length * elementsPerItem * 2); + extendedArray.set(buffer); + + return extendedArray; + } + + return buffer; + } + + function getLocations(program, uniformOrAttributeNames) { + var foundLocations = {}; + for (var i = 0; i < uniformOrAttributeNames.length; ++i) { + var name = uniformOrAttributeNames[i]; + var location = -1; + if (name[0] === 'a' && name[1] === '_') { + location = gl.getAttribLocation(program, name); + if (location === -1) { + throw new Error("Program doesn't have required attribute: " + name); + } + + foundLocations[name.slice(2)] = location; + } else if (name[0] === 'u' && name[1] === '_') { + location = gl.getUniformLocation(program, name); + if (location === null) { + throw new Error("Program doesn't have required uniform: " + name); + } + + foundLocations[name.slice(2)] = location; + } else { + throw new Error("Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'"); + } + } + + return foundLocations; + } +} + +function copyArrayPart(array, to, from, elementsCount) { + for (var i = 0; i < elementsCount; ++i) { + array[to + i] = array[from + i]; + } +} + +function swapArrayPart(array, from, to, elementsCount) { + for (var i = 0; i < elementsCount; ++i) { + var tmp = array[from + i]; + array[from + i] = array[to + i]; + array[to + i] = tmp; + } +} + +},{}],54:[function(require,module,exports){ +var Texture = require('./texture.js'); + +module.exports = webglAtlas; + +/** + * My naive implementation of textures atlas. It allows clients to load + * multiple images into atlas and get canvas representing all of them. + * + * @param tilesPerTexture - indicates how many images can be loaded to one + * texture of the atlas. If number of loaded images exceeds this + * parameter a new canvas will be created. + */ +function webglAtlas(tilesPerTexture) { + var tilesPerRow = Math.sqrt(tilesPerTexture || 1024) << 0, + tileSize = tilesPerRow, + lastLoadedIdx = 1, + loadedImages = {}, + dirtyTimeoutId, + skipedDirty = 0, + textures = [], + trackedUrls = []; + + if (!isPowerOf2(tilesPerTexture)) { + throw "Tiles per texture should be power of two."; + } + + // this is the return object + var api = { + /** + * indicates whether atlas has changed texture in it. If true then + * some of the textures has isDirty flag set as well. + */ + isDirty: false, + + /** + * Clears any signs of atlas changes. + */ + clearDirty: clearDirty, + + /** + * Removes given url from collection of tiles in the atlas. + */ + remove: remove, + + /** + * Gets all textures in the atlas. + */ + getTextures: getTextures, + + /** + * Gets coordinates of the given image in the atlas. Coordinates is an object: + * {offset : int } - where offset is an absolute position of the image in the + * atlas. + * + * Absolute means it can be larger than tilesPerTexture parameter, and in that + * case clients should get next texture in getTextures() collection. + */ + getCoordinates: getCoordinates, + + /** + * Asynchronously Loads the image to the atlas. Cross-domain security + * limitation applies. + */ + load: load + }; + + return api; + + function clearDirty() { + var i; + api.isDirty = false; + for (i = 0; i < textures.length; ++i) { + textures[i].isDirty = false; + } + } + + function remove(imgUrl) { + var coordinates = loadedImages[imgUrl]; + if (!coordinates) { + return false; + } + delete loadedImages[imgUrl]; + lastLoadedIdx -= 1; + + + if (lastLoadedIdx === coordinates.offset) { + return true; // Ignore if it's last image in the whole set. + } + + var tileToRemove = getTileCoordinates(coordinates.offset), + lastTileInSet = getTileCoordinates(lastLoadedIdx); + + copy(lastTileInSet, tileToRemove); + + var replacedOffset = loadedImages[trackedUrls[lastLoadedIdx]]; + replacedOffset.offset = coordinates.offset; + trackedUrls[coordinates.offset] = trackedUrls[lastLoadedIdx]; + + markDirty(); + return true; + } + + function getTextures() { + return textures; // I trust you... + } + + function getCoordinates(imgUrl) { + return loadedImages[imgUrl]; + } + + function load(imgUrl, callback) { + if (loadedImages.hasOwnProperty(imgUrl)) { + callback(loadedImages[imgUrl]); + } else { + var img = new window.Image(), + imgId = lastLoadedIdx; + + lastLoadedIdx += 1; + img.crossOrigin = "anonymous"; + img.onload = function() { + markDirty(); + drawAt(imgId, img, callback); + }; + + img.src = imgUrl; + } + } + + function createTexture() { + var texture = new Texture(tilesPerRow * tileSize); + textures.push(texture); + } + + function drawAt(tileNumber, img, callback) { + var tilePosition = getTileCoordinates(tileNumber), + coordinates = { + offset: tileNumber + }; + + if (tilePosition.textureNumber >= textures.length) { + createTexture(); + } + var currentTexture = textures[tilePosition.textureNumber]; + + currentTexture.ctx.drawImage(img, tilePosition.col * tileSize, tilePosition.row * tileSize, tileSize, tileSize); + trackedUrls[tileNumber] = img.src; + + loadedImages[img.src] = coordinates; + currentTexture.isDirty = true; + + callback(coordinates); + } + + function getTileCoordinates(absolutePosition) { + var textureNumber = (absolutePosition / tilesPerTexture) << 0, + localTileNumber = (absolutePosition % tilesPerTexture), + row = (localTileNumber / tilesPerRow) << 0, + col = (localTileNumber % tilesPerRow); + + return { + textureNumber: textureNumber, + row: row, + col: col + }; + } + + function markDirtyNow() { + api.isDirty = true; + skipedDirty = 0; + dirtyTimeoutId = null; + } + + function markDirty() { + // delay this call, since it results in texture reload + if (dirtyTimeoutId) { + window.clearTimeout(dirtyTimeoutId); + skipedDirty += 1; + dirtyTimeoutId = null; + } + + if (skipedDirty > 10) { + markDirtyNow(); + } else { + dirtyTimeoutId = window.setTimeout(markDirtyNow, 400); + } + } + + function copy(from, to) { + var fromCanvas = textures[from.textureNumber].canvas, + toCtx = textures[to.textureNumber].ctx, + x = to.col * tileSize, + y = to.row * tileSize; + + toCtx.drawImage(fromCanvas, from.col * tileSize, from.row * tileSize, tileSize, tileSize, x, y, tileSize, tileSize); + textures[from.textureNumber].isDirty = true; + textures[to.textureNumber].isDirty = true; + } +} + +function isPowerOf2(n) { + return (n & (n - 1)) === 0; +} + +},{"./texture.js":52}],55:[function(require,module,exports){ +module.exports = webglImage; + +/** + * Represents a model for image. + */ +function webglImage(size, src) { + return { + /** + * Gets texture index where current image is placed. + */ + _texture : 0, + + /** + * Gets offset in the texture where current image is placed. + */ + _offset : 0, + + /** + * Gets size of the square with the image. + */ + size : typeof size === 'number' ? size : 32, + + /** + * Source of the image. If image is coming not from your domain + * certain origin restrictions applies. + * See http://www.khronos.org/registry/webgl/specs/latest/#4.2 for more details. + */ + src : src + }; +} + +},{}],56:[function(require,module,exports){ +/** + * @fileOverview Defines an image nodes for webglGraphics class. + * Shape of nodes is square. + * + * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + */ + +var WebglAtlas = require('./webglAtlas.js'); +var glUtils = require('./webgl.js'); + +module.exports = webglImageNodeProgram; + +/** + * Defines simple UI for nodes in webgl renderer. Each node is rendered as an image. + */ +function webglImageNodeProgram() { + // WebGL is gian state machine, we store some properties of the state here: + var ATTRIBUTES_PER_PRIMITIVE = 18; + var nodesFS = createNodeFragmentShader(); + var nodesVS = createNodeVertexShader(); + var tilesPerTexture = 1024; // TODO: Get based on max texture size + var atlas; + var program; + var gl; + var buffer; + var utils; + var locations; + var nodesCount = 0; + var nodes = new Float32Array(64); + var width; + var height; + var transform; + var sizeDirty; + + + return { + load: load, + + /** + * Updates position of current node in the buffer of nodes. + * + * @param idx - index of current node. + * @param pos - new position of the node. + */ + position: position, + + createNode: createNode, + + removeNode: removeNode, + + replaceProperties: replaceProperties, + + updateTransform: updateTransform, + + updateSize: updateSize, + + render: render + }; + + function refreshTexture(texture, idx) { + if (texture.nativeObject) { + gl.deleteTexture(texture.nativeObject); + } + + var nativeObject = gl.createTexture(); + gl.activeTexture(gl["TEXTURE" + idx]); + gl.bindTexture(gl.TEXTURE_2D, nativeObject); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.canvas); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST); + + gl.generateMipmap(gl.TEXTURE_2D); + gl.uniform1i(locations["sampler" + idx], idx); + + texture.nativeObject = nativeObject; + } + + function ensureAtlasTextureUpdated() { + if (atlas.isDirty) { + var textures = atlas.getTextures(), + i; + for (i = 0; i < textures.length; ++i) { + if (textures[i].isDirty || !textures[i].nativeObject) { + refreshTexture(textures[i], i); + } + } + + atlas.clearDirty(); + } + } + + function load(glContext) { + gl = glContext; + utils = glUtils(glContext); + + atlas = new WebglAtlas(tilesPerTexture); + + program = utils.createProgram(nodesVS, nodesFS); + gl.useProgram(program); + locations = utils.getLocations(program, ["a_vertexPos", "a_customAttributes", "u_screenSize", "u_transform", "u_sampler0", "u_sampler1", "u_sampler2", "u_sampler3", "u_tilesPerTexture"]); + + gl.uniform1f(locations.tilesPerTexture, tilesPerTexture); + + gl.enableVertexAttribArray(locations.vertexPos); + gl.enableVertexAttribArray(locations.customAttributes); + + buffer = gl.createBuffer(); + } + + function position(nodeUI, pos) { + var idx = nodeUI.id * ATTRIBUTES_PER_PRIMITIVE; + nodes[idx] = pos.x - nodeUI.size; + nodes[idx + 1] = pos.y - nodeUI.size; + nodes[idx + 2] = nodeUI._offset * 4; + + nodes[idx + 3] = pos.x + nodeUI.size; + nodes[idx + 4] = pos.y - nodeUI.size; + nodes[idx + 5] = nodeUI._offset * 4 + 1; + + nodes[idx + 6] = pos.x - nodeUI.size; + nodes[idx + 7] = pos.y + nodeUI.size; + nodes[idx + 8] = nodeUI._offset * 4 + 2; + + nodes[idx + 9] = pos.x - nodeUI.size; + nodes[idx + 10] = pos.y + nodeUI.size; + nodes[idx + 11] = nodeUI._offset * 4 + 2; + + nodes[idx + 12] = pos.x + nodeUI.size; + nodes[idx + 13] = pos.y - nodeUI.size; + nodes[idx + 14] = nodeUI._offset * 4 + 1; + + nodes[idx + 15] = pos.x + nodeUI.size; + nodes[idx + 16] = pos.y + nodeUI.size; + nodes[idx + 17] = nodeUI._offset * 4 + 3; + } + + function createNode(ui) { + nodes = utils.extendArray(nodes, nodesCount, ATTRIBUTES_PER_PRIMITIVE); + nodesCount += 1; + + var coordinates = atlas.getCoordinates(ui.src); + if (coordinates) { + ui._offset = coordinates.offset; + } else { + ui._offset = 0; + // Image is not yet loaded into the atlas. Reload it: + atlas.load(ui.src, function(coordinates) { + ui._offset = coordinates.offset; + }); + } + } + + function removeNode(nodeUI) { + if (nodesCount > 0) { + nodesCount -= 1; + } + + if (nodeUI.id < nodesCount && nodesCount > 0) { + if (nodeUI.src) { + atlas.remove(nodeUI.src); + } + + utils.copyArrayPart(nodes, nodeUI.id * ATTRIBUTES_PER_PRIMITIVE, nodesCount * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); + } + } + + function replaceProperties(replacedNode, newNode) { + newNode._offset = replacedNode._offset; + } + + function updateTransform(newTransform) { + sizeDirty = true; + transform = newTransform; + } + + function updateSize(w, h) { + width = w; + height = h; + sizeDirty = true; + } + + function render() { + gl.useProgram(program); + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData(gl.ARRAY_BUFFER, nodes, gl.DYNAMIC_DRAW); + + if (sizeDirty) { + sizeDirty = false; + gl.uniformMatrix4fv(locations.transform, false, transform); + gl.uniform2f(locations.screenSize, width, height); + } + + gl.vertexAttribPointer(locations.vertexPos, 2, gl.FLOAT, false, 3 * Float32Array.BYTES_PER_ELEMENT, 0); + gl.vertexAttribPointer(locations.customAttributes, 1, gl.FLOAT, false, 3 * Float32Array.BYTES_PER_ELEMENT, 2 * 4); + + ensureAtlasTextureUpdated(); + + gl.drawArrays(gl.TRIANGLES, 0, nodesCount * 6); + } +} + +// TODO: Use glslify for shaders +function createNodeFragmentShader() { + return [ + "precision mediump float;", + "varying vec4 color;", + "varying vec3 vTextureCoord;", + "uniform sampler2D u_sampler0;", + "uniform sampler2D u_sampler1;", + "uniform sampler2D u_sampler2;", + "uniform sampler2D u_sampler3;", + + "void main(void) {", + " if (vTextureCoord.z == 0.) {", + " gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);", + " } else if (vTextureCoord.z == 1.) {", + " gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);", + " } else if (vTextureCoord.z == 2.) {", + " gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);", + " } else if (vTextureCoord.z == 3.) {", + " gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);", + " } else { gl_FragColor = vec4(0, 1, 0, 1); }", + "}" + ].join("\n"); +} + +function createNodeVertexShader() { + return [ + "attribute vec2 a_vertexPos;", + + "attribute float a_customAttributes;", + "uniform vec2 u_screenSize;", + "uniform mat4 u_transform;", + "uniform float u_tilesPerTexture;", + "varying vec3 vTextureCoord;", + + "void main(void) {", + " gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);", + "float corner = mod(a_customAttributes, 4.);", + "float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);", + "float tilesPerRow = sqrt(u_tilesPerTexture);", + "float tileSize = 1./tilesPerRow;", + "float tileColumn = mod(tileIndex, tilesPerRow);", + "float tileRow = floor(tileIndex/tilesPerRow);", + + "if(corner == 0.0) {", + " vTextureCoord.xy = vec2(0, 1);", + "} else if(corner == 1.0) {", + " vTextureCoord.xy = vec2(1, 1);", + "} else if(corner == 2.0) {", + " vTextureCoord.xy = vec2(0, 0);", + "} else {", + " vTextureCoord.xy = vec2(1, 0);", + "}", + + "vTextureCoord *= tileSize;", + "vTextureCoord.x += tileColumn * tileSize;", + "vTextureCoord.y += tileRow * tileSize;", + "vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);", + "}" + ].join("\n"); +} },{"./webgl.js":53,"./webglAtlas.js":54}],57:[function(require,module,exports){ -var documentEvents = require('../Utils/documentEvents.js'); - -module.exports = webglInputEvents; - -/** - * Monitors graph-related mouse input in webgl graphics and notifies subscribers. - * - * @param {Viva.Graph.View.webglGraphics} webglGraphics - */ -function webglInputEvents(webglGraphics) { - if (webglGraphics.webglInputEvents) { - // Don't listen twice, if we are already attached to this graphics: - return webglGraphics.webglInputEvents; - } - - var mouseCapturedNode = null, - mouseEnterCallback = [], - mouseLeaveCallback = [], - mouseDownCallback = [], - mouseUpCallback = [], - mouseMoveCallback = [], - clickCallback = [], - dblClickCallback = [], - prevSelectStart, - boundRect; - - var root = webglGraphics.getGraphicsRoot(); - startListen(root); - - var api = { - mouseEnter: mouseEnter, - mouseLeave: mouseLeave, - mouseDown: mouseDown, - mouseUp: mouseUp, - mouseMove: mouseMove, - click: click, - dblClick: dblClick, - mouseCapture: mouseCapture, - releaseMouseCapture: releaseMouseCapture - }; - - // TODO I don't remember why this is needed: - webglGraphics.webglInputEvents = api; - - return api; - - function releaseMouseCapture() { - mouseCapturedNode = null; - } - - function mouseCapture(node) { - mouseCapturedNode = node; - } - - function dblClick(callback) { - if (typeof callback === 'function') { - dblClickCallback.push(callback); - } - return api; - } - - function click(callback) { - if (typeof callback === 'function') { - clickCallback.push(callback); - } - return api; - } - - function mouseMove(callback) { - if (typeof callback === 'function') { - mouseMoveCallback.push(callback); - } - return api; - } - - function mouseUp(callback) { - if (typeof callback === 'function') { - mouseUpCallback.push(callback); - } - return api; - } - - function mouseDown(callback) { - if (typeof callback === 'function') { - mouseDownCallback.push(callback); - } - return api; - } - - function mouseLeave(callback) { - if (typeof callback === 'function') { - mouseLeaveCallback.push(callback); - } - return api; - } - - function mouseEnter(callback) { - if (typeof callback === 'function') { - mouseEnterCallback.push(callback); - } - return api; - } - - function preciseCheck(nodeUI, x, y) { - if (nodeUI && nodeUI.size) { - var pos = nodeUI.position, - half = nodeUI.size; - - return pos.x - half < x && x < pos.x + half && - pos.y - half < y && y < pos.y + half; - } - - return true; - } - - function getNodeAtClientPos(pos) { - return webglGraphics.getNodeAtClientPos(pos, preciseCheck); - } - - function stopPropagation(e) { - if (e.stopPropagation) { - e.stopPropagation(); - } else { - e.cancelBubble = true; - } - } - - function handleDisabledEvent(e) { - stopPropagation(e); - return false; - } - - function invoke(callbacksChain, args) { - var i, stopPropagation; - for (i = 0; i < callbacksChain.length; i += 1) { - stopPropagation = callbacksChain[i].apply(undefined, args); - if (stopPropagation) { - return true; - } - } - } - - function startListen(root) { - var pos = { - x: 0, - y: 0 - }, - lastFound = null, - lastUpdate = 1, - lastClickTime = +new Date(), - - handleMouseMove = function(e) { - invoke(mouseMoveCallback, [lastFound, e]); - pos.x = e.clientX; - pos.y = e.clientY; - }, - - handleMouseUp = function() { - documentEvents.off('mousemove', handleMouseMove); - documentEvents.off('mouseup', handleMouseUp); - }, - - updateBoundRect = function() { - boundRect = root.getBoundingClientRect(); - }; - - window.addEventListener('resize', updateBoundRect); - updateBoundRect(); - - // mouse move inside container serves only to track mouse enter/leave events. - root.addEventListener('mousemove', - function(e) { - if (mouseCapturedNode) { - return; - } - if (lastUpdate++ % 7 === 0) { - // since there is no bullet proof method to detect resize - // event, we preemptively update the bounding rectangle - updateBoundRect(); - lastUpdate = 1; - } - var cancelBubble = false, - node; - - pos.x = e.clientX - boundRect.left; - pos.y = e.clientY - boundRect.top; - - node = getNodeAtClientPos(pos); - - if (node && lastFound !== node) { - lastFound = node; - cancelBubble = cancelBubble || invoke(mouseEnterCallback, [lastFound]); - } else if (node === null && lastFound !== node) { - cancelBubble = cancelBubble || invoke(mouseLeaveCallback, [lastFound]); - lastFound = null; - } - - if (cancelBubble) { - stopPropagation(e); - } - }); - - root.addEventListener('mousedown', - function(e) { - var cancelBubble = false, - args; - updateBoundRect(); - pos.x = e.clientX - boundRect.left; - pos.y = e.clientY - boundRect.top; - - args = [getNodeAtClientPos(pos), e]; - if (args[0]) { - cancelBubble = invoke(mouseDownCallback, args); - // we clicked on a node. Following drag should be handled on document events: - documentEvents.on('mousemove', handleMouseMove); - documentEvents.on('mouseup', handleMouseUp); - - prevSelectStart = window.document.onselectstart; - - window.document.onselectstart = handleDisabledEvent; - - lastFound = args[0]; - } else { - lastFound = null; - } - if (cancelBubble) { - stopPropagation(e); - } - }); - - root.addEventListener('mouseup', - function(e) { - var clickTime = +new Date(), - args; - - pos.x = e.clientX - boundRect.left; - pos.y = e.clientY - boundRect.top; - - var nodeAtClientPos = getNodeAtClientPos(pos); - var sameNode = nodeAtClientPos === lastFound; - args = [nodeAtClientPos || lastFound, e]; - if (args[0]) { - window.document.onselectstart = prevSelectStart; - - if (clickTime - lastClickTime < 400 && sameNode) { - invoke(dblClickCallback, args); - } else { - invoke(clickCallback, args); - } - lastClickTime = clickTime; - - if (invoke(mouseUpCallback, args)) { - stopPropagation(e); - } - } - }); - } -} +var documentEvents = require('../Utils/documentEvents.js'); + +module.exports = webglInputEvents; + +/** + * Monitors graph-related mouse input in webgl graphics and notifies subscribers. + * + * @param {Viva.Graph.View.webglGraphics} webglGraphics + */ +function webglInputEvents(webglGraphics) { + if (webglGraphics.webglInputEvents) { + // Don't listen twice, if we are already attached to this graphics: + return webglGraphics.webglInputEvents; + } + + var mouseCapturedNode = null, + mouseEnterCallback = [], + mouseLeaveCallback = [], + mouseDownCallback = [], + mouseUpCallback = [], + mouseMoveCallback = [], + clickCallback = [], + dblClickCallback = [], + prevSelectStart, + boundRect; + + var root = webglGraphics.getGraphicsRoot(); + startListen(root); + + var api = { + mouseEnter: mouseEnter, + mouseLeave: mouseLeave, + mouseDown: mouseDown, + mouseUp: mouseUp, + mouseMove: mouseMove, + click: click, + dblClick: dblClick, + mouseCapture: mouseCapture, + releaseMouseCapture: releaseMouseCapture + }; + + // TODO I don't remember why this is needed: + webglGraphics.webglInputEvents = api; + + return api; + + function releaseMouseCapture() { + mouseCapturedNode = null; + } + + function mouseCapture(node) { + mouseCapturedNode = node; + } + + function dblClick(callback) { + if (typeof callback === 'function') { + dblClickCallback.push(callback); + } + return api; + } + + function click(callback) { + if (typeof callback === 'function') { + clickCallback.push(callback); + } + return api; + } + + function mouseMove(callback) { + if (typeof callback === 'function') { + mouseMoveCallback.push(callback); + } + return api; + } + + function mouseUp(callback) { + if (typeof callback === 'function') { + mouseUpCallback.push(callback); + } + return api; + } + + function mouseDown(callback) { + if (typeof callback === 'function') { + mouseDownCallback.push(callback); + } + return api; + } + + function mouseLeave(callback) { + if (typeof callback === 'function') { + mouseLeaveCallback.push(callback); + } + return api; + } + + function mouseEnter(callback) { + if (typeof callback === 'function') { + mouseEnterCallback.push(callback); + } + return api; + } + + function preciseCheck(nodeUI, x, y) { + if (nodeUI && nodeUI.size) { + var pos = nodeUI.position, + half = nodeUI.size; + + return pos.x - half < x && x < pos.x + half && + pos.y - half < y && y < pos.y + half; + } + + return true; + } + + function getNodeAtClientPos(pos) { + return webglGraphics.getNodeAtClientPos(pos, preciseCheck); + } + + function stopPropagation(e) { + if (e.stopPropagation) { + e.stopPropagation(); + } else { + e.cancelBubble = true; + } + } + + function handleDisabledEvent(e) { + stopPropagation(e); + return false; + } + + function invoke(callbacksChain, args) { + var i, stopPropagation; + for (i = 0; i < callbacksChain.length; i += 1) { + stopPropagation = callbacksChain[i].apply(undefined, args); + if (stopPropagation) { + return true; + } + } + } + + function startListen(root) { + var pos = { + x: 0, + y: 0 + }, + lastFound = null, + lastUpdate = 1, + lastClickTime = +new Date(), + + handleMouseMove = function(e) { + invoke(mouseMoveCallback, [lastFound, e]); + pos.x = e.clientX; + pos.y = e.clientY; + }, + + handleMouseUp = function() { + documentEvents.off('mousemove', handleMouseMove); + documentEvents.off('mouseup', handleMouseUp); + }, + + updateBoundRect = function() { + boundRect = root.getBoundingClientRect(); + }; + + window.addEventListener('resize', updateBoundRect); + updateBoundRect(); + + // mouse move inside container serves only to track mouse enter/leave events. + root.addEventListener('mousemove', + function(e) { + if (mouseCapturedNode) { + return; + } + if (lastUpdate++ % 7 === 0) { + // since there is no bullet proof method to detect resize + // event, we preemptively update the bounding rectangle + updateBoundRect(); + lastUpdate = 1; + } + var cancelBubble = false, + node; + + pos.x = e.clientX - boundRect.left; + pos.y = e.clientY - boundRect.top; + + node = getNodeAtClientPos(pos); + + if (node && lastFound !== node) { + lastFound = node; + cancelBubble = cancelBubble || invoke(mouseEnterCallback, [lastFound]); + } else if (node === null && lastFound !== node) { + cancelBubble = cancelBubble || invoke(mouseLeaveCallback, [lastFound]); + lastFound = null; + } + + if (cancelBubble) { + stopPropagation(e); + } + }); + + root.addEventListener('mousedown', + function(e) { + var cancelBubble = false, + args; + updateBoundRect(); + pos.x = e.clientX - boundRect.left; + pos.y = e.clientY - boundRect.top; + + args = [getNodeAtClientPos(pos), e]; + if (args[0]) { + cancelBubble = invoke(mouseDownCallback, args); + // we clicked on a node. Following drag should be handled on document events: + documentEvents.on('mousemove', handleMouseMove); + documentEvents.on('mouseup', handleMouseUp); + + prevSelectStart = window.document.onselectstart; + + window.document.onselectstart = handleDisabledEvent; + + lastFound = args[0]; + } else { + lastFound = null; + } + if (cancelBubble) { + stopPropagation(e); + } + }); + + root.addEventListener('mouseup', + function(e) { + var clickTime = +new Date(), + args; + + pos.x = e.clientX - boundRect.left; + pos.y = e.clientY - boundRect.top; + + var nodeAtClientPos = getNodeAtClientPos(pos); + var sameNode = nodeAtClientPos === lastFound; + args = [nodeAtClientPos || lastFound, e]; + if (args[0]) { + window.document.onselectstart = prevSelectStart; + + if (clickTime - lastClickTime < 400 && sameNode) { + invoke(dblClickCallback, args); + } else { + invoke(clickCallback, args); + } + lastClickTime = clickTime; + + if (invoke(mouseUpCallback, args)) { + stopPropagation(e); + } + } + }); + } +} },{"../Utils/documentEvents.js":40}],58:[function(require,module,exports){ -var parseColor = require('./parseColor.js'); - -module.exports = webglLine; - -/** - * Defines a webgl line. This class has no rendering logic at all, - * it's just passed to corresponding shader and the shader should - * figure out how to render it. - * - */ -function webglLine(color) { - return { - /** - * Gets or sets color of the line. If you set this property externally - * make sure it always come as integer of 0xRRGGBBAA format - */ - color: parseColor(color) - }; -} +var parseColor = require('./parseColor.js'); + +module.exports = webglLine; + +/** + * Defines a webgl line. This class has no rendering logic at all, + * it's just passed to corresponding shader and the shader should + * figure out how to render it. + * + */ +function webglLine(color) { + return { + /** + * Gets or sets color of the line. If you set this property externally + * make sure it always come as integer of 0xRRGGBBAA format + */ + color: parseColor(color) + }; +} },{"./parseColor.js":51}],59:[function(require,module,exports){ -/** - * @fileOverview Defines a naive form of links for webglGraphics class. - * This form allows to change color of links. - **/ - -var glUtils = require('./webgl.js'); - -module.exports = webglLinkProgram; - -/** - * Defines UI for links in webgl renderer. - */ -function webglLinkProgram() { - var ATTRIBUTES_PER_PRIMITIVE = 6, // primitive is Line with two points. Each has x,y and color = 3 * 2 attributes. - BYTES_PER_LINK = 2 * (2 * Float32Array.BYTES_PER_ELEMENT + Uint32Array.BYTES_PER_ELEMENT), // two nodes * (x, y + color) - linksFS = [ - 'precision mediump float;', - 'varying vec4 color;', - 'void main(void) {', - ' gl_FragColor = color;', - '}' - ].join('\n'), - - linksVS = [ - 'attribute vec2 a_vertexPos;', - 'attribute vec4 a_color;', - - 'uniform vec2 u_screenSize;', - 'uniform mat4 u_transform;', - - 'varying vec4 color;', - - 'void main(void) {', - ' gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);', - ' color = a_color.abgr;', - '}' - ].join('\n'), - - program, - gl, - buffer, - utils, - locations, - linksCount = 0, - frontLinkId, // used to track z-index of links. - storage = new ArrayBuffer(16 * BYTES_PER_LINK), - positions = new Float32Array(storage), - colors = new Uint32Array(storage), - width, - height, - transform, - sizeDirty, - - ensureEnoughStorage = function () { - // TODO: this is a duplicate of webglNodeProgram code. Extract it to webgl.js - if ((linksCount+1)*BYTES_PER_LINK > storage.byteLength) { - // Every time we run out of space create new array twice bigger. - // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs - var extendedStorage = new ArrayBuffer(storage.byteLength * 2), - extendedPositions = new Float32Array(extendedStorage), - extendedColors = new Uint32Array(extendedStorage); - - extendedColors.set(colors); // should be enough to copy just one view. - positions = extendedPositions; - colors = extendedColors; - storage = extendedStorage; - } - }; - - return { - load : function (glContext) { - gl = glContext; - utils = glUtils(glContext); - - program = utils.createProgram(linksVS, linksFS); - gl.useProgram(program); - locations = utils.getLocations(program, ['a_vertexPos', 'a_color', 'u_screenSize', 'u_transform']); - - gl.enableVertexAttribArray(locations.vertexPos); - gl.enableVertexAttribArray(locations.color); - - buffer = gl.createBuffer(); - }, - - position: function (linkUi, fromPos, toPos) { - var linkIdx = linkUi.id, - offset = linkIdx * ATTRIBUTES_PER_PRIMITIVE; - positions[offset] = fromPos.x; - positions[offset + 1] = fromPos.y; - colors[offset + 2] = linkUi.color; - - positions[offset + 3] = toPos.x; - positions[offset + 4] = toPos.y; - colors[offset + 5] = linkUi.color; - }, - - createLink : function (ui) { - ensureEnoughStorage(); - - linksCount += 1; - frontLinkId = ui.id; - }, - - removeLink : function (ui) { - if (linksCount > 0) { linksCount -= 1; } - // swap removed link with the last link. This will give us O(1) performance for links removal: - if (ui.id < linksCount && linksCount > 0) { - // using colors as a view to array buffer is okay here. - utils.copyArrayPart(colors, ui.id * ATTRIBUTES_PER_PRIMITIVE, linksCount * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); - } - }, - - updateTransform : function (newTransform) { - sizeDirty = true; - transform = newTransform; - }, - - updateSize : function (w, h) { - width = w; - height = h; - sizeDirty = true; - }, - - render : function () { - gl.useProgram(program); - gl.bindBuffer(gl.ARRAY_BUFFER, buffer); - gl.bufferData(gl.ARRAY_BUFFER, storage, gl.DYNAMIC_DRAW); - - if (sizeDirty) { - sizeDirty = false; - gl.uniformMatrix4fv(locations.transform, false, transform); - gl.uniform2f(locations.screenSize, width, height); - } - - gl.vertexAttribPointer(locations.vertexPos, 2, gl.FLOAT, false, 3 * Float32Array.BYTES_PER_ELEMENT, 0); - gl.vertexAttribPointer(locations.color, 4, gl.UNSIGNED_BYTE, true, 3 * Float32Array.BYTES_PER_ELEMENT, 2 * 4); - - gl.drawArrays(gl.LINES, 0, linksCount * 2); - - frontLinkId = linksCount - 1; - }, - - bringToFront : function (link) { - if (frontLinkId > link.id) { - utils.swapArrayPart(positions, link.id * ATTRIBUTES_PER_PRIMITIVE, frontLinkId * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); - } - if (frontLinkId > 0) { - frontLinkId -= 1; - } - }, - - getFrontLinkId : function () { - return frontLinkId; - } - }; -} +/** + * @fileOverview Defines a naive form of links for webglGraphics class. + * This form allows to change color of links. + **/ + +var glUtils = require('./webgl.js'); + +module.exports = webglLinkProgram; + +/** + * Defines UI for links in webgl renderer. + */ +function webglLinkProgram() { + var ATTRIBUTES_PER_PRIMITIVE = 6, // primitive is Line with two points. Each has x,y and color = 3 * 2 attributes. + BYTES_PER_LINK = 2 * (2 * Float32Array.BYTES_PER_ELEMENT + Uint32Array.BYTES_PER_ELEMENT), // two nodes * (x, y + color) + linksFS = [ + 'precision mediump float;', + 'varying vec4 color;', + 'void main(void) {', + ' gl_FragColor = color;', + '}' + ].join('\n'), + + linksVS = [ + 'attribute vec2 a_vertexPos;', + 'attribute vec4 a_color;', + + 'uniform vec2 u_screenSize;', + 'uniform mat4 u_transform;', + + 'varying vec4 color;', + + 'void main(void) {', + ' gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0.0, 1.0);', + ' color = a_color.abgr;', + '}' + ].join('\n'), + + program, + gl, + buffer, + utils, + locations, + linksCount = 0, + frontLinkId, // used to track z-index of links. + storage = new ArrayBuffer(16 * BYTES_PER_LINK), + positions = new Float32Array(storage), + colors = new Uint32Array(storage), + width, + height, + transform, + sizeDirty, + + ensureEnoughStorage = function () { + // TODO: this is a duplicate of webglNodeProgram code. Extract it to webgl.js + if ((linksCount+1)*BYTES_PER_LINK > storage.byteLength) { + // Every time we run out of space create new array twice bigger. + // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs + var extendedStorage = new ArrayBuffer(storage.byteLength * 2), + extendedPositions = new Float32Array(extendedStorage), + extendedColors = new Uint32Array(extendedStorage); + + extendedColors.set(colors); // should be enough to copy just one view. + positions = extendedPositions; + colors = extendedColors; + storage = extendedStorage; + } + }; + + return { + load : function (glContext) { + gl = glContext; + utils = glUtils(glContext); + + program = utils.createProgram(linksVS, linksFS); + gl.useProgram(program); + locations = utils.getLocations(program, ['a_vertexPos', 'a_color', 'u_screenSize', 'u_transform']); + + gl.enableVertexAttribArray(locations.vertexPos); + gl.enableVertexAttribArray(locations.color); + + buffer = gl.createBuffer(); + }, + + position: function (linkUi, fromPos, toPos) { + var linkIdx = linkUi.id, + offset = linkIdx * ATTRIBUTES_PER_PRIMITIVE; + positions[offset] = fromPos.x; + positions[offset + 1] = fromPos.y; + colors[offset + 2] = linkUi.color; + + positions[offset + 3] = toPos.x; + positions[offset + 4] = toPos.y; + colors[offset + 5] = linkUi.color; + }, + + createLink : function (ui) { + ensureEnoughStorage(); + + linksCount += 1; + frontLinkId = ui.id; + }, + + removeLink : function (ui) { + if (linksCount > 0) { linksCount -= 1; } + // swap removed link with the last link. This will give us O(1) performance for links removal: + if (ui.id < linksCount && linksCount > 0) { + // using colors as a view to array buffer is okay here. + utils.copyArrayPart(colors, ui.id * ATTRIBUTES_PER_PRIMITIVE, linksCount * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); + } + }, + + updateTransform : function (newTransform) { + sizeDirty = true; + transform = newTransform; + }, + + updateSize : function (w, h) { + width = w; + height = h; + sizeDirty = true; + }, + + render : function () { + gl.useProgram(program); + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData(gl.ARRAY_BUFFER, storage, gl.DYNAMIC_DRAW); + + if (sizeDirty) { + sizeDirty = false; + gl.uniformMatrix4fv(locations.transform, false, transform); + gl.uniform2f(locations.screenSize, width, height); + } + + gl.vertexAttribPointer(locations.vertexPos, 2, gl.FLOAT, false, 3 * Float32Array.BYTES_PER_ELEMENT, 0); + gl.vertexAttribPointer(locations.color, 4, gl.UNSIGNED_BYTE, true, 3 * Float32Array.BYTES_PER_ELEMENT, 2 * 4); + + gl.drawArrays(gl.LINES, 0, linksCount * 2); + + frontLinkId = linksCount - 1; + }, + + bringToFront : function (link) { + if (frontLinkId > link.id) { + utils.swapArrayPart(positions, link.id * ATTRIBUTES_PER_PRIMITIVE, frontLinkId * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); + } + if (frontLinkId > 0) { + frontLinkId -= 1; + } + }, + + getFrontLinkId : function () { + return frontLinkId; + } + }; +} },{"./webgl.js":53}],60:[function(require,module,exports){ -/** - * @fileOverview Defines a naive form of nodes for webglGraphics class. - * This form allows to change color of node. Shape of nodes is rectangular. - * - * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka - */ - -var glUtils = require('./webgl.js'); - -module.exports = webglNodeProgram; - -/** - * Defines simple UI for nodes in webgl renderer. Each node is rendered as square. Color and size can be changed. - */ -function webglNodeProgram() { - var ATTRIBUTES_PER_PRIMITIVE = 4; // Primitive is point, x, y, size, color - // x, y, z - floats, color = uint. - var BYTES_PER_NODE = 3 * Float32Array.BYTES_PER_ELEMENT + Uint32Array.BYTES_PER_ELEMENT; - var nodesFS = [ - 'precision mediump float;', - 'varying vec4 color;', - - 'void main(void) {', - ' gl_FragColor = color;', - '}' - ].join('\n'); - var nodesVS = [ - 'attribute vec3 a_vertexPos;', - 'attribute vec4 a_color;', - 'uniform vec2 u_screenSize;', - 'uniform mat4 u_transform;', - 'varying vec4 color;', - - 'void main(void) {', - ' gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);', - ' gl_PointSize = a_vertexPos.z * u_transform[0][0];', - ' color = a_color.abgr;', - '}' - ].join('\n'); - - var program; - var gl; - var buffer; - var locations; - var utils; - var storage = new ArrayBuffer(16 * BYTES_PER_NODE); - var positions = new Float32Array(storage); - var colors = new Uint32Array(storage); - var nodesCount = 0; - var width; - var height; - var transform; - var sizeDirty; - - return { - load: load, - - /** - * Updates position of node in the buffer of nodes. - * - * @param idx - index of current node. - * @param pos - new position of the node. - */ - position: position, - - updateTransform: updateTransform, - - updateSize: updateSize, - - removeNode: removeNode, - - createNode: createNode, - - replaceProperties: replaceProperties, - - render: render - }; - - function ensureEnoughStorage() { - if ((nodesCount + 1) * BYTES_PER_NODE >= storage.byteLength) { - // Every time we run out of space create new array twice bigger. - // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs - var extendedStorage = new ArrayBuffer(storage.byteLength * 2), - extendedPositions = new Float32Array(extendedStorage), - extendedColors = new Uint32Array(extendedStorage); - - extendedColors.set(colors); // should be enough to copy just one view. - positions = extendedPositions; - colors = extendedColors; - storage = extendedStorage; - } - } - - function load(glContext) { - gl = glContext; - utils = glUtils(glContext); - - program = utils.createProgram(nodesVS, nodesFS); - gl.useProgram(program); - locations = utils.getLocations(program, ['a_vertexPos', 'a_color', 'u_screenSize', 'u_transform']); - - gl.enableVertexAttribArray(locations.vertexPos); - gl.enableVertexAttribArray(locations.color); - - buffer = gl.createBuffer(); - } - - function position(nodeUI, pos) { - var idx = nodeUI.id; - - positions[idx * ATTRIBUTES_PER_PRIMITIVE] = pos.x; - positions[idx * ATTRIBUTES_PER_PRIMITIVE + 1] = -pos.y; - positions[idx * ATTRIBUTES_PER_PRIMITIVE + 2] = nodeUI.size; - - colors[idx * ATTRIBUTES_PER_PRIMITIVE + 3] = nodeUI.color; - } - - function updateTransform(newTransform) { - sizeDirty = true; - transform = newTransform; - } - - function updateSize(w, h) { - width = w; - height = h; - sizeDirty = true; - } - - function removeNode(node) { - if (nodesCount > 0) { - nodesCount -= 1; - } - - if (node.id < nodesCount && nodesCount > 0) { - // we can use colors as a 'view' into array array buffer. - utils.copyArrayPart(colors, node.id * ATTRIBUTES_PER_PRIMITIVE, nodesCount * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); - } - } - - function createNode() { - ensureEnoughStorage(); - nodesCount += 1; - } - - function replaceProperties(/* replacedNode, newNode */) {} - - function render() { - gl.useProgram(program); - gl.bindBuffer(gl.ARRAY_BUFFER, buffer); - gl.bufferData(gl.ARRAY_BUFFER, storage, gl.DYNAMIC_DRAW); - - if (sizeDirty) { - sizeDirty = false; - gl.uniformMatrix4fv(locations.transform, false, transform); - gl.uniform2f(locations.screenSize, width, height); - } - - gl.vertexAttribPointer(locations.vertexPos, 3, gl.FLOAT, false, ATTRIBUTES_PER_PRIMITIVE * Float32Array.BYTES_PER_ELEMENT, 0); - gl.vertexAttribPointer(locations.color, 4, gl.UNSIGNED_BYTE, true, ATTRIBUTES_PER_PRIMITIVE * Float32Array.BYTES_PER_ELEMENT, 3 * 4); - - gl.drawArrays(gl.POINTS, 0, nodesCount); - } -} +/** + * @fileOverview Defines a naive form of nodes for webglGraphics class. + * This form allows to change color of node. Shape of nodes is rectangular. + * + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka + */ + +var glUtils = require('./webgl.js'); + +module.exports = webglNodeProgram; + +/** + * Defines simple UI for nodes in webgl renderer. Each node is rendered as square. Color and size can be changed. + */ +function webglNodeProgram() { + var ATTRIBUTES_PER_PRIMITIVE = 4; // Primitive is point, x, y, size, color + // x, y, z - floats, color = uint. + var BYTES_PER_NODE = 3 * Float32Array.BYTES_PER_ELEMENT + Uint32Array.BYTES_PER_ELEMENT; + var nodesFS = [ + 'precision mediump float;', + 'varying vec4 color;', + + 'void main(void) {', + ' gl_FragColor = color;', + '}' + ].join('\n'); + var nodesVS = [ + 'attribute vec3 a_vertexPos;', + 'attribute vec4 a_color;', + 'uniform vec2 u_screenSize;', + 'uniform mat4 u_transform;', + 'varying vec4 color;', + + 'void main(void) {', + ' gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);', + ' gl_PointSize = a_vertexPos.z * u_transform[0][0];', + ' color = a_color.abgr;', + '}' + ].join('\n'); + + var program; + var gl; + var buffer; + var locations; + var utils; + var storage = new ArrayBuffer(16 * BYTES_PER_NODE); + var positions = new Float32Array(storage); + var colors = new Uint32Array(storage); + var nodesCount = 0; + var width; + var height; + var transform; + var sizeDirty; + + return { + load: load, + + /** + * Updates position of node in the buffer of nodes. + * + * @param idx - index of current node. + * @param pos - new position of the node. + */ + position: position, + + updateTransform: updateTransform, + + updateSize: updateSize, + + removeNode: removeNode, + + createNode: createNode, + + replaceProperties: replaceProperties, + + render: render + }; + + function ensureEnoughStorage() { + if ((nodesCount + 1) * BYTES_PER_NODE >= storage.byteLength) { + // Every time we run out of space create new array twice bigger. + // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs + var extendedStorage = new ArrayBuffer(storage.byteLength * 2), + extendedPositions = new Float32Array(extendedStorage), + extendedColors = new Uint32Array(extendedStorage); + + extendedColors.set(colors); // should be enough to copy just one view. + positions = extendedPositions; + colors = extendedColors; + storage = extendedStorage; + } + } + + function load(glContext) { + gl = glContext; + utils = glUtils(glContext); + + program = utils.createProgram(nodesVS, nodesFS); + gl.useProgram(program); + locations = utils.getLocations(program, ['a_vertexPos', 'a_color', 'u_screenSize', 'u_transform']); + + gl.enableVertexAttribArray(locations.vertexPos); + gl.enableVertexAttribArray(locations.color); + + buffer = gl.createBuffer(); + } + + function position(nodeUI, pos) { + var idx = nodeUI.id; + + positions[idx * ATTRIBUTES_PER_PRIMITIVE] = pos.x; + positions[idx * ATTRIBUTES_PER_PRIMITIVE + 1] = -pos.y; + positions[idx * ATTRIBUTES_PER_PRIMITIVE + 2] = nodeUI.size; + + colors[idx * ATTRIBUTES_PER_PRIMITIVE + 3] = nodeUI.color; + } + + function updateTransform(newTransform) { + sizeDirty = true; + transform = newTransform; + } + + function updateSize(w, h) { + width = w; + height = h; + sizeDirty = true; + } + + function removeNode(node) { + if (nodesCount > 0) { + nodesCount -= 1; + } + + if (node.id < nodesCount && nodesCount > 0) { + // we can use colors as a 'view' into array array buffer. + utils.copyArrayPart(colors, node.id * ATTRIBUTES_PER_PRIMITIVE, nodesCount * ATTRIBUTES_PER_PRIMITIVE, ATTRIBUTES_PER_PRIMITIVE); + } + } + + function createNode() { + ensureEnoughStorage(); + nodesCount += 1; + } + + function replaceProperties(/* replacedNode, newNode */) {} + + function render() { + gl.useProgram(program); + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData(gl.ARRAY_BUFFER, storage, gl.DYNAMIC_DRAW); + + if (sizeDirty) { + sizeDirty = false; + gl.uniformMatrix4fv(locations.transform, false, transform); + gl.uniform2f(locations.screenSize, width, height); + } + + gl.vertexAttribPointer(locations.vertexPos, 3, gl.FLOAT, false, ATTRIBUTES_PER_PRIMITIVE * Float32Array.BYTES_PER_ELEMENT, 0); + gl.vertexAttribPointer(locations.color, 4, gl.UNSIGNED_BYTE, true, ATTRIBUTES_PER_PRIMITIVE * Float32Array.BYTES_PER_ELEMENT, 3 * 4); + + gl.drawArrays(gl.POINTS, 0, nodesCount); + } +} },{"./webgl.js":53}],61:[function(require,module,exports){ -var parseColor = require('./parseColor.js'); - -module.exports = webglSquare; - -/** - * Can be used as a callback in the webglGraphics.node() function, to - * create a custom looking node. - * - * @param size - size of the node in pixels. - * @param color - color of the node in '#rrggbbaa' or '#rgb' format. - */ -function webglSquare(size, color) { - return { - /** - * Gets or sets size of the square side. - */ - size: typeof size === 'number' ? size : 10, - - /** - * Gets or sets color of the square. - */ - color: parseColor(color) - }; -} +var parseColor = require('./parseColor.js'); + +module.exports = webglSquare; + +/** + * Can be used as a callback in the webglGraphics.node() function, to + * create a custom looking node. + * + * @param size - size of the node in pixels. + * @param color - color of the node in '#rrggbbaa' or '#rgb' format. + */ +function webglSquare(size, color) { + return { + /** + * Gets or sets size of the square side. + */ + size: typeof size === 'number' ? size : 10, + + /** + * Gets or sets color of the square. + */ + color: parseColor(color) + }; +} },{"./parseColor.js":51}],62:[function(require,module,exports){ -// todo: this should be generated at build time. -module.exports = '0.8.1'; +// todo: this should be generated at build time. +module.exports = '0.8.1'; },{}]},{},[1])(1) }); \ No newline at end of file From e18e39aeba6d234eb4467b1d5940288369c7b324 Mon Sep 17 00:00:00 2001 From: Andriy Kashcha Date: Mon, 7 Aug 2017 22:33:41 -0700 Subject: [PATCH 241/276] 0.10.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 38ab72a..260c84e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.9.0", + "version": "0.10.0", "description": "Graph Drawing Library", "main": "src/viva", "directories": { From 7bd2802643ba0a059164691bafc57ae80ffbad74 Mon Sep 17 00:00:00 2001 From: Andriy Kashcha Date: Thu, 22 Feb 2018 20:57:36 -0800 Subject: [PATCH 242/276] removed old blogspot reference --- dist/vivagraph.js | 3634 ++++++++++++++-------------- src/Utils/timer.js | 2 +- src/View/svgGraphics.js | 2 +- src/WebGL/webgl.js | 2 +- src/WebGL/webglImageNodeProgram.js | 2 +- 5 files changed, 1821 insertions(+), 1821 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 4f0fad5..0d0cf06 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -1,116 +1,116 @@ !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Viva=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= 0; - } else if (typeof interactive === 'boolean') { - return interactive; - } - return true; // default setting - } - - function prepareSettings() { - container = container || window.document.body; - layout = layout || forceDirected(graph, { - springLength: 80, - springCoeff: 0.0002, - }); - graphics = graphics || svgGraphics(graph, { - container: container - }); - - if (!settings.hasOwnProperty('renderLinks')) { - settings.renderLinks = true; - } - - settings.prerender = settings.prerender || 0; - inputManager = (graphics.inputManager || domInputManager)(graph, graphics); - } - - function renderGraph() { - graphics.beginRender(); - - // todo: move this check graphics - if (settings.renderLinks) { - graphics.renderLinks(); - } - graphics.renderNodes(); - graphics.endRender(); - } - - function onRenderFrame() { - isStable = layout.step() && !userInteraction; - renderGraph(); - - return !isStable; - } - - function renderIterations(iterationsCount) { - if (animationTimer) { - totalIterationsCount += iterationsCount; - return; - } - - if (iterationsCount) { - totalIterationsCount += iterationsCount; - - animationTimer = timer(function() { - return onRenderFrame(); - }, FRAME_INTERVAL); - } else { - currentStep = 0; - totalIterationsCount = 0; - animationTimer = timer(onRenderFrame, FRAME_INTERVAL); - } - } - - function resetStable() { - if (isPaused) { - return; - } - - isStable = false; - animationTimer.restart(); - } - - function prerender() { - // To get good initial positions for the graph - // perform several prerender steps in background. - if (typeof settings.prerender === 'number' && settings.prerender > 0) { - for (var i = 0; i < settings.prerender; i += 1) { - layout.step(); - } - } - } - - function updateCenter() { - var graphRect = layout.getGraphRect(), - containerSize = getDimension(container); - - var cx = (graphRect.x2 + graphRect.x1) / 2; - var cy = (graphRect.y2 + graphRect.y1) / 2; - transform.offsetX = containerSize.width / 2 - (cx * transform.scale - cx); - transform.offsetY = containerSize.height / 2 - (cy * transform.scale - cy); - graphics.graphCenterChanged(transform.offsetX, transform.offsetY); - - updateCenterRequired = false; - } - - function createNodeUi(node) { - var nodePosition = layout.getNodePosition(node.id); - graphics.addNode(node, nodePosition); - } - - function removeNodeUi(node) { - graphics.releaseNode(node); - } - - function createLinkUi(link) { - var linkPosition = layout.getLinkPosition(link.id); - graphics.addLink(link, linkPosition); - } - - function removeLinkUi(link) { - graphics.releaseLink(link); - } - - function listenNodeEvents(node) { - if (!isInteractive('node')) { - return; - } - - var wasPinned = false; - - // TODO: This may not be memory efficient. Consider reusing handlers object. - inputManager.bindDragNDrop(node, { - onStart: function() { - wasPinned = layout.isNodePinned(node); - layout.pinNode(node, true); - userInteraction = true; - resetStable(); - }, - onDrag: function(e, offset) { - var oldPos = layout.getNodePosition(node.id); - layout.setNodePosition(node.id, - oldPos.x + offset.x / transform.scale, - oldPos.y + offset.y / transform.scale); - - userInteraction = true; - - renderGraph(); - }, - onStop: function() { - layout.pinNode(node, wasPinned); - userInteraction = false; - } - }); - } - - function releaseNodeEvents(node) { - inputManager.bindDragNDrop(node, null); - } - - function initDom() { - graphics.init(container); - - graph.forEachNode(createNodeUi); - - if (settings.renderLinks) { - graph.forEachLink(createLinkUi); - } - } - - function releaseDom() { - graphics.release(container); - } - - function processNodeChange(change) { - var node = change.node; - - if (change.changeType === 'add') { - createNodeUi(node); - listenNodeEvents(node); - if (updateCenterRequired) { - updateCenter(); - } - } else if (change.changeType === 'remove') { - releaseNodeEvents(node); - removeNodeUi(node); - if (graph.getNodesCount() === 0) { - updateCenterRequired = true; // Next time when node is added - center the graph. - } - } else if (change.changeType === 'update') { - releaseNodeEvents(node); - removeNodeUi(node); - - createNodeUi(node); - listenNodeEvents(node); - } - } - - function processLinkChange(change) { - var link = change.link; - if (change.changeType === 'add') { - if (settings.renderLinks) { - createLinkUi(link); - } - } else if (change.changeType === 'remove') { - if (settings.renderLinks) { - removeLinkUi(link); - } - } else if (change.changeType === 'update') { - throw 'Update type is not implemented. TODO: Implement me!'; - } - } - - function onGraphChanged(changes) { - var i, change; - for (i = 0; i < changes.length; i += 1) { - change = changes[i]; - if (change.node) { - processNodeChange(change); - } else if (change.link) { - processLinkChange(change); - } - } - - resetStable(); - } - - function onWindowResized() { - updateCenter(); - onRenderFrame(); - } - - function releaseContainerDragManager() { - if (containerDrag) { - containerDrag.release(); - containerDrag = null; - } - } - - function releaseGraphEvents() { - graph.off('changed', onGraphChanged); - } - - function scale(out, scrollPoint) { - if (!scrollPoint) { - var containerSize = getDimension(container); - scrollPoint = { - x: containerSize.width / 2, - y: containerSize.height / 2 - }; - } - var scaleFactor = Math.pow(1 + 0.4, out ? -0.2 : 0.2); - transform.scale = graphics.scale(scaleFactor, scrollPoint); - - renderGraph(); - publicEvents.fire('scale', transform.scale); - - return transform.scale; - } - - function listenToEvents() { - windowEvents.on('resize', onWindowResized); - - releaseContainerDragManager(); - if (isInteractive('drag')) { - containerDrag = dragndrop(container); - containerDrag.onDrag(function(e, offset) { - graphics.translateRel(offset.x, offset.y); - - renderGraph(); - publicEvents.fire('drag', offset); - }); - } - - if (isInteractive('scroll')) { - if (!containerDrag) { - containerDrag = dragndrop(container); - } - containerDrag.onScroll(function(e, scaleOffset, scrollPoint) { - scale(scaleOffset < 0, scrollPoint); - }); - } - - graph.forEachNode(listenNodeEvents); - - releaseGraphEvents(); - graph.on('changed', onGraphChanged); - } - - function stopListenToEvents() { - rendererInitialized = false; - releaseGraphEvents(); - releaseContainerDragManager(); - windowEvents.off('resize', onWindowResized); - publicEvents.off(); - animationTimer.stop(); - - graph.forEachLink(function(link) { - if (settings.renderLinks) { - removeLinkUi(link); - } - }); - - graph.forEachNode(function(node) { - releaseNodeEvents(node); - removeNodeUi(node); - }); - - layout.dispose(); - releaseDom(); - } -} +/** + * @fileOverview Defines a graph renderer that uses CSS based drawings. + * + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka + */ -},{"../Input/domInputManager.js":34,"../Input/dragndrop.js":35,"../Utils/getDimensions.js":42,"../Utils/timer.js":46,"../Utils/windowEvents.js":47,"./svgGraphics.js":49,"ngraph.events":7,"ngraph.forcelayout":9}],49:[function(require,module,exports){ -/** - * @fileOverview Defines a graph renderer that uses SVG based drawings. - * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com - */ - -module.exports = svgGraphics; - -var svg = require('simplesvg'); -var eventify = require('ngraph.events'); -var domInputManager = require('../Input/domInputManager.js'); - -/** - * Performs svg-based graph rendering. This module does not perform - * layout, but only visualizes nodes and edges of the graph. - */ -function svgGraphics() { - var svgContainer, - svgRoot, - offsetX = 0, - offsetY = 0, - initCallback, - actualScale = 1, - allNodes = {}, - allLinks = {}, -/*jshint unused: false */ - nodeBuilder = function (node) { - return svg("rect") - .attr("width", 10) - .attr("height", 10) - .attr("fill", "#00a2e8"); - }, - - nodePositionCallback = function (nodeUI, pos) { - // TODO: Remove magic 5. It should be half of the width or height of the node. - nodeUI.attr("x", pos.x - 5) - .attr("y", pos.y - 5); - }, - - linkBuilder = function (link) { - return svg("line").attr("stroke", "#999"); - }, - - linkPositionCallback = function (linkUI, fromPos, toPos) { - linkUI.attr("x1", fromPos.x) - .attr("y1", fromPos.y) - .attr("x2", toPos.x) - .attr("y2", toPos.y); - }, - - fireRescaled = function (graphics) { - // TODO: maybe we shall copy changes? - graphics.fire("rescaled"); - }, - - cachedPos = {x : 0, y: 0}, - cachedFromPos = {x : 0, y: 0}, - cachedToPos = {x : 0, y: 0}, - - updateTransform = function () { - if (svgContainer) { - var transform = "matrix(" + actualScale + ", 0, 0," + actualScale + "," + offsetX + "," + offsetY + ")"; - svgContainer.attr("transform", transform); - } - }; - - svgRoot = createSvgRoot(); - - var graphics = { - getNodeUI: function (nodeId) { - return allNodes[nodeId]; - }, - - getLinkUI: function (linkId) { - return allLinks[linkId]; - }, - - /** - * Sets the callback that creates node representation. - * - * @param builderCallback a callback function that accepts graph node - * as a parameter and must return an element representing this node. - * - * @returns If builderCallbackOrNode is a valid callback function, instance of this is returned; - * Otherwise undefined value is returned - */ - node : function (builderCallback) { - if (typeof builderCallback !== "function") { - return; // todo: throw? This is not compatible with old versions - } - - nodeBuilder = builderCallback; - - return this; - }, - - /** - * Sets the callback that creates link representation - * - * @param builderCallback a callback function that accepts graph link - * as a parameter and must return an element representing this link. - * - * @returns If builderCallback is a valid callback function, instance of this is returned; - * Otherwise undefined value is returned. - */ - link : function (builderCallback) { - if (typeof builderCallback !== "function") { - return; // todo: throw? This is not compatible with old versions - } - - linkBuilder = builderCallback; - return this; - }, - - /** - * Allows to override default position setter for the node with a new - * function. newPlaceCallback(nodeUI, position, node) is function which - * is used by updateNodePosition(). - */ - placeNode : function (newPlaceCallback) { - nodePositionCallback = newPlaceCallback; - return this; - }, - - placeLink : function (newPlaceLinkCallback) { - linkPositionCallback = newPlaceLinkCallback; - return this; - }, - - /** - * Called every before renderer starts rendering. - */ - beginRender : function () {}, - - /** - * Called every time when renderer finishes one step of rendering. - */ - endRender : function () {}, - - /** - * Sets translate operation that should be applied to all nodes and links. - */ - graphCenterChanged : function (x, y) { - offsetX = x; - offsetY = y; - updateTransform(); - }, - - /** - * Default input manager listens to DOM events to process nodes drag-n-drop - */ - inputManager : domInputManager, - - translateRel : function (dx, dy) { - var p = svgRoot.createSVGPoint(), - t = svgContainer.getCTM(), - origin = svgRoot.createSVGPoint().matrixTransform(t.inverse()); - - p.x = dx; - p.y = dy; - - p = p.matrixTransform(t.inverse()); - p.x = (p.x - origin.x) * t.a; - p.y = (p.y - origin.y) * t.d; - - t.e += p.x; - t.f += p.y; - - var transform = "matrix(" + t.a + ", 0, 0," + t.d + "," + t.e + "," + t.f + ")"; - svgContainer.attr("transform", transform); - }, - - scale : function (scaleFactor, scrollPoint) { - var p = svgRoot.createSVGPoint(); - p.x = scrollPoint.x; - p.y = scrollPoint.y; - - p = p.matrixTransform(svgContainer.getCTM().inverse()); // translate to SVG coordinates - - // Compute new scale matrix in current mouse position - var k = svgRoot.createSVGMatrix().translate(p.x, p.y).scale(scaleFactor).translate(-p.x, -p.y), - t = svgContainer.getCTM().multiply(k); - - actualScale = t.a; - offsetX = t.e; - offsetY = t.f; - var transform = "matrix(" + t.a + ", 0, 0," + t.d + "," + t.e + "," + t.f + ")"; - svgContainer.attr("transform", transform); - - fireRescaled(this); - return actualScale; - }, - - resetScale : function () { - actualScale = 1; - var transform = "matrix(1, 0, 0, 1, 0, 0)"; - svgContainer.attr("transform", transform); - fireRescaled(this); - return this; - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render. - */ - init : function (container) { - container.appendChild(svgRoot); - updateTransform(); - // Notify the world if someone waited for update. TODO: should send an event - if (typeof initCallback === "function") { - initCallback(svgRoot); - } - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider release occupied resources. - */ - release : function (container) { - if (svgRoot && container) { - container.removeChild(svgRoot); - } - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render given link of the graph - * - * @param link - model of a link - */ - addLink: function (link, pos) { - var linkUI = linkBuilder(link); - if (!linkUI) { return; } - linkUI.position = pos; - linkUI.link = link; - allLinks[link.id] = linkUI; - if (svgContainer.childElementCount > 0) { - svgContainer.insertBefore(linkUI, svgContainer.firstChild); - } else { - svgContainer.appendChild(linkUI); - } - return linkUI; - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider remove link from rendering surface. - * - * @param linkUI visual representation of the link created by link() execution. - **/ - releaseLink : function (link) { - var linkUI = allLinks[link.id]; - if (linkUI) { - svgContainer.removeChild(linkUI); - delete allLinks[link.id]; - } - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render given node of the graph. - * - * @param nodeUI visual representation of the node created by node() execution. - **/ - addNode : function (node, pos) { - var nodeUI = nodeBuilder(node); - if (!nodeUI) { - return; - } - nodeUI.position = pos; - nodeUI.node = node; - allNodes[node.id] = nodeUI; - - svgContainer.appendChild(nodeUI); - - return nodeUI; - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider remove node from rendering surface. - * - * @param node graph's node - **/ - releaseNode : function (node) { - var nodeUI = allNodes[node.id]; - if (nodeUI) { - svgContainer.removeChild(nodeUI); - delete allNodes[node.id]; - } - }, - - renderNodes : function () { - for (var key in allNodes) { - if (allNodes.hasOwnProperty(key)) { - var nodeUI = allNodes[key]; - cachedPos.x = nodeUI.position.x; - cachedPos.y = nodeUI.position.y; - nodePositionCallback(nodeUI, cachedPos, nodeUI.node); - } - } - }, - - renderLinks : function () { - for (var key in allLinks) { - if (allLinks.hasOwnProperty(key)) { - var linkUI = allLinks[key]; - cachedFromPos.x = linkUI.position.from.x; - cachedFromPos.y = linkUI.position.from.y; - cachedToPos.x = linkUI.position.to.x; - cachedToPos.y = linkUI.position.to.y; - linkPositionCallback(linkUI, cachedFromPos, cachedToPos, linkUI.link); - } - } - }, - - /** - * Returns root element which hosts graphics. - */ - getGraphicsRoot : function (callbackWhenReady) { - // todo: should fire an event, instead of having this context. - if (typeof callbackWhenReady === "function") { - if (svgRoot) { - callbackWhenReady(svgRoot); - } else { - initCallback = callbackWhenReady; - } - } - return svgRoot; - }, - /** - * Returns root SVG element. - * - * Note: This is internal method specific to this renderer - */ - getSvgRoot : function () { - return svgRoot; - } - }; - - - // Let graphics fire events before we return it to the caller. - eventify(graphics); - - return graphics; - - function createSvgRoot() { - var svgRoot = svg("svg"); - - svgContainer = svg("g") - .attr("buffered-rendering", "dynamic"); - - svgRoot.appendChild(svgContainer); - return svgRoot; - } -} +module.exports = renderer; -},{"../Input/domInputManager.js":34,"ngraph.events":7,"simplesvg":28}],50:[function(require,module,exports){ -/** - * @fileOverview Defines a graph renderer that uses WebGL based drawings. - * - * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka - */ - -module.exports = webglGraphics; - -var webglInputManager = require('../Input/webglInputManager.js'); -var webglLinkProgram = require('../WebGL/webglLinkProgram.js'); -var webglNodeProgram = require('../WebGL/webglNodeProgram.js'); -var webglSquare = require('../WebGL/webglSquare.js'); -var webglLine = require('../WebGL/webglLine.js'); -var eventify = require('ngraph.events'); -var merge = require('ngraph.merge'); - -/** - * Performs webgl-based graph rendering. This module does not perform - * layout, but only visualizes nodes and edges of the graph. - * - * @param options - to customize graphics behavior. Currently supported parameter - * enableBlending - true by default, allows to use transparency in node/links colors. - * preserveDrawingBuffer - false by default, tells webgl to preserve drawing buffer. - * See https://www.khronos.org/registry/webgl/specs/1.0/#5.2 - */ - -function webglGraphics(options) { - options = merge(options, { - enableBlending : true, - preserveDrawingBuffer : false, - clearColor: false, - clearColorValue : { - r : 1, - g : 1, - b : 1, - a : 1 - } - }); - - var container, - graphicsRoot, - gl, - width, - height, - nodesCount = 0, - linksCount = 0, - transform = [ - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - ], - userPlaceNodeCallback, - userPlaceLinkCallback, - nodes = [], - links = [], - initCallback, - - allNodes = {}, - allLinks = {}, - linkProgram = webglLinkProgram(), - nodeProgram = webglNodeProgram(), -/*jshint unused: false */ - nodeUIBuilder = function (node) { - return webglSquare(); // Just make a square, using provided gl context (a nodeProgram); - }, - - linkUIBuilder = function (link) { - return webglLine(0xb3b3b3ff); - }, -/*jshint unused: true */ - updateTransformUniform = function () { - linkProgram.updateTransform(transform); - nodeProgram.updateTransform(transform); - }, - - resetScaleInternal = function () { - transform = [1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1]; - }, - - updateSize = function () { - if (container && graphicsRoot) { - width = graphicsRoot.width = Math.max(container.offsetWidth, 1); - height = graphicsRoot.height = Math.max(container.offsetHeight, 1); - if (gl) { gl.viewport(0, 0, width, height); } - if (linkProgram) { linkProgram.updateSize(width / 2, height / 2); } - if (nodeProgram) { nodeProgram.updateSize(width / 2, height / 2); } - } - }, - - fireRescaled = function (graphics) { - graphics.fire("rescaled"); - }; - - graphicsRoot = window.document.createElement("canvas"); - - var graphics = { - getLinkUI: function (linkId) { - return allLinks[linkId]; - }, - - getNodeUI: function (nodeId) { - return allNodes[nodeId]; - }, - - /** - * Sets the callback that creates node representation. - * - * @param builderCallback a callback function that accepts graph node - * as a parameter and must return an element representing this node. - * - * @returns If builderCallbackOrNode is a valid callback function, instance of this is returned; - * Otherwise undefined value is returned - */ - node : function (builderCallback) { - if (typeof builderCallback !== "function") { - return; // todo: throw? This is not compatible with old versions - } - - nodeUIBuilder = builderCallback; - - return this; - }, - - /** - * Sets the callback that creates link representation - * - * @param builderCallback a callback function that accepts graph link - * as a parameter and must return an element representing this link. - * - * @returns If builderCallback is a valid callback function, instance of this is returned; - * Otherwise undefined value is returned. - */ - link : function (builderCallback) { - if (typeof builderCallback !== "function") { - return; // todo: throw? This is not compatible with old versions - } - - linkUIBuilder = builderCallback; - return this; - }, - - - /** - * Allows to override default position setter for the node with a new - * function. newPlaceCallback(nodeUI, position) is function which - * is used by updateNodePosition(). - */ - placeNode : function (newPlaceCallback) { - userPlaceNodeCallback = newPlaceCallback; - return this; - }, - - placeLink : function (newPlaceLinkCallback) { - userPlaceLinkCallback = newPlaceLinkCallback; - return this; - }, - - /** - * Custom input manager listens to mouse events to process nodes drag-n-drop inside WebGL canvas - */ - inputManager : webglInputManager, - - /** - * Called every time before renderer starts rendering. - */ - beginRender : function () { - // this function could be replaced by this.init, - // based on user options. - }, - - /** - * Called every time when renderer finishes one step of rendering. - */ - endRender : function () { - if (linksCount > 0) { - linkProgram.render(); - } - if (nodesCount > 0) { - nodeProgram.render(); - } - }, - - bringLinkToFront : function (linkUI) { - var frontLinkId = linkProgram.getFrontLinkId(), - srcLinkId, - temp; - - linkProgram.bringToFront(linkUI); - - if (frontLinkId > linkUI.id) { - srcLinkId = linkUI.id; - - temp = links[frontLinkId]; - links[frontLinkId] = links[srcLinkId]; - links[frontLinkId].id = frontLinkId; - links[srcLinkId] = temp; - links[srcLinkId].id = srcLinkId; - } - }, - - /** - * Sets translate operation that should be applied to all nodes and links. - */ - graphCenterChanged : function (x, y) { - transform[12] = (2 * x / width) - 1; - transform[13] = 1 - (2 * y / height); - updateTransformUniform(); - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render given link of the graph - * - * @param link - model of a link - */ - addLink: function (link, boundPosition) { - var uiid = linksCount++, - ui = linkUIBuilder(link); - ui.id = uiid; - ui.pos = boundPosition; - - linkProgram.createLink(ui); - - links[uiid] = ui; - allLinks[link.id] = ui; - return ui; - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render given node of the graph. - * - * @param nodeUI visual representation of the node created by node() execution. - **/ - addNode : function (node, boundPosition) { - var uiid = nodesCount++, - ui = nodeUIBuilder(node); - - ui.id = uiid; - ui.position = boundPosition; - ui.node = node; - - nodeProgram.createNode(ui); - - nodes[uiid] = ui; - allNodes[node.id] = ui; - return ui; - }, - - translateRel : function (dx, dy) { - transform[12] += (2 * transform[0] * dx / width) / transform[0]; - transform[13] -= (2 * transform[5] * dy / height) / transform[5]; - updateTransformUniform(); - }, - - scale : function (scaleFactor, scrollPoint) { - // Transform scroll point to clip-space coordinates: - var cx = 2 * scrollPoint.x / width - 1, - cy = 1 - (2 * scrollPoint.y) / height; - - cx -= transform[12]; - cy -= transform[13]; - - transform[12] += cx * (1 - scaleFactor); - transform[13] += cy * (1 - scaleFactor); - - transform[0] *= scaleFactor; - transform[5] *= scaleFactor; - - updateTransformUniform(); - fireRescaled(this); - - return transform[0]; - }, - - resetScale : function () { - resetScaleInternal(); - - if (gl) { - updateSize(); - // TODO: what is this? - // gl.useProgram(linksProgram); - // gl.uniform2f(linksProgram.screenSize, width, height); - updateTransformUniform(); - } - return this; - }, - - /** - * Resizes the graphic without resetting the scale. - * Useful with viva graph in a dynamic container - */ - updateSize: updateSize, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render. - */ - init : function (c) { - var contextParameters = {}; - - if (options.preserveDrawingBuffer) { - contextParameters.preserveDrawingBuffer = true; - } - - container = c; - - updateSize(); - resetScaleInternal(); - container.appendChild(graphicsRoot); - - - gl = graphicsRoot.getContext("experimental-webgl", contextParameters); - if (!gl) { - var msg = "Could not initialize WebGL. Seems like the browser doesn't support it."; - window.alert(msg); - throw msg; - } - if (options.enableBlending) { - gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); - gl.enable(gl.BLEND); - } - if (options.clearColor) { - var color = options.clearColorValue; - gl.clearColor(color.r, color.g, color.b, color.a); - // TODO: not the best way, really. Should come up with something better - // what if we need more updates inside beginRender, like depth buffer? - this.beginRender = function () { - gl.clear(gl.COLOR_BUFFER_BIT); - }; - } - - linkProgram.load(gl); - linkProgram.updateSize(width / 2, height / 2); - - nodeProgram.load(gl); - nodeProgram.updateSize(width / 2, height / 2); - - updateTransformUniform(); - - // Notify the world if someone waited for update. TODO: should send an event - if (typeof initCallback === "function") { - initCallback(graphicsRoot); - } - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider release occupied resources. - */ - release : function (container) { - if (graphicsRoot && container) { - container.removeChild(graphicsRoot); - // TODO: anything else? - } - }, - - /** - * Checks whether webgl is supported by this browser. - */ - isSupported : function () { - var c = window.document.createElement("canvas"), - gl = c && c.getContext && c.getContext("experimental-webgl"); - return gl; - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider remove link from rendering surface. - * - * @param linkUI visual representation of the link created by link() execution. - **/ - releaseLink : function (link) { - if (linksCount > 0) { linksCount -= 1; } - var linkUI = allLinks[link.id]; - delete allLinks[link.id]; - - linkProgram.removeLink(linkUI); - - var linkIdToRemove = linkUI.id; - if (linkIdToRemove < linksCount) { - if (linksCount === 0 || linksCount === linkIdToRemove) { - return; // no more links or removed link is the last one. - } - - var lastLinkUI = links[linksCount]; - links[linkIdToRemove] = lastLinkUI; - lastLinkUI.id = linkIdToRemove; - } - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider remove node from rendering surface. - * - * @param nodeUI visual representation of the node created by node() execution. - **/ - releaseNode : function (node) { - if (nodesCount > 0) { nodesCount -= 1; } - var nodeUI = allNodes[node.id]; - delete allNodes[node.id]; - - nodeProgram.removeNode(nodeUI); - - var nodeIdToRemove = nodeUI.id; - if (nodeIdToRemove < nodesCount) { - if (nodesCount === 0 || nodesCount === nodeIdToRemove) { - return; // no more nodes or removed node is the last in the list. - } - - var lastNodeUI = nodes[nodesCount]; - - nodes[nodeIdToRemove] = lastNodeUI; - lastNodeUI.id = nodeIdToRemove; - - // Since concrete shaders may cache properties in the UI element - // we are letting them to make this swap (e.g. image node shader - // uses this approach to update node's offset in the atlas) - nodeProgram.replaceProperties(nodeUI, lastNodeUI); - } - }, - - renderNodes: function () { - var pos = {x : 0, y : 0}; - // WebGL coordinate system is different. Would be better - // to have this transform in the shader code, but it would - // require every shader to be updated.. - for (var i = 0; i < nodesCount; ++i) { - var ui = nodes[i]; - pos.x = ui.position.x; - pos.y = ui.position.y; - if (userPlaceNodeCallback) { - userPlaceNodeCallback(ui, pos); - } - - nodeProgram.position(ui, pos); - } - }, - - renderLinks: function () { - if (this.omitLinksRendering) { return; } - - var toPos = {x : 0, y : 0}; - var fromPos = {x : 0, y : 0}; - for (var i = 0; i < linksCount; ++i) { - var ui = links[i]; - var pos = ui.pos.from; - fromPos.x = pos.x; - fromPos.y = -pos.y; - pos = ui.pos.to; - toPos.x = pos.x; - toPos.y = -pos.y; - if (userPlaceLinkCallback) { - userPlaceLinkCallback(ui, fromPos, toPos); - } - - linkProgram.position(ui, fromPos, toPos); - } - }, - - /** - * Returns root element which hosts graphics. - */ - getGraphicsRoot : function (callbackWhenReady) { - // todo: should fire an event, instead of having this context. - if (typeof callbackWhenReady === "function") { - if (graphicsRoot) { - callbackWhenReady(graphicsRoot); - } else { - initCallback = callbackWhenReady; - } - } - return graphicsRoot; - }, - - /** - * Updates default shader which renders nodes - * - * @param newProgram to use for nodes. - */ - setNodeProgram : function (newProgram) { - if (!gl && newProgram) { - // Nothing created yet. Just set shader to the new one - // and let initialization logic take care about the rest. - nodeProgram = newProgram; - } else if (newProgram) { - throw "Not implemented. Cannot swap shader on the fly... Yet."; - // TODO: unload old shader and reinit. - } - }, - - /** - * Updates default shader which renders links - * - * @param newProgram to use for links. - */ - setLinkProgram : function (newProgram) { - if (!gl && newProgram) { - // Nothing created yet. Just set shader to the new one - // and let initialization logic take care about the rest. - linkProgram = newProgram; - } else if (newProgram) { - throw "Not implemented. Cannot swap shader on the fly... Yet."; - // TODO: unload old shader and reinit. - } - }, - - /** - * Transforms client coordinates into layout coordinates. Client coordinates - * are DOM coordinates relative to the rendering container. Layout - * coordinates are those assigned by by layout algorithm to each node. - * - * @param {Object} p - a point object with `x` and `y` attributes. - * This method mutates p. - */ - transformClientToGraphCoordinates: function (p) { - // TODO: could be a problem when container has margins? - // normalize - p.x = ((2 * p.x) / width) - 1; - p.y = 1 - ((2 * p.y) / height); - - // apply transform - p.x = (p.x - transform[12]) / transform[0]; - p.y = (p.y - transform[13]) / transform[5]; - - // transform to graph coordinates - p.x = p.x * (width / 2); - p.y = p.y * (-height / 2); - - return p; - }, - - /** - * Transforms WebGL coordinates into client coordinates. Reverse of - * `transformClientToGraphCoordinates()` - * - * @param {Object} p - a point object with `x` and `y` attributes, which - * represents a layout coordinate. This method mutates p. - */ - transformGraphToClientCoordinates: function (p) { - // TODO: could be a problem when container has margins? - // transform from graph coordinates - p.x = p.x / (width / 2); - p.y = p.y / (-height / 2); - - // apply transform - p.x = (p.x * transform[0]) + transform[12]; - p.y = (p.y * transform[5]) + transform[13]; - - // denormalize - p.x = ((p.x + 1) * width) / 2; - p.y = ((1 - p.y) * height) / 2; - - return p; - }, - - getNodeAtClientPos: function (clientPos, preciseCheck) { - if (typeof preciseCheck !== "function") { - // we don't know anything about your node structure here :( - // potentially this could be delegated to node program, but for - // right now, we are giving up if you don't pass boundary check - // callback. It answers to a question is nodeUI covers (x, y) - return null; - } - // first transform to graph coordinates: - this.transformClientToGraphCoordinates(clientPos); - // now using precise check iterate over each node and find one within box: - // TODO: This is poor O(N) performance. - for (var i = 0; i < nodesCount; ++i) { - if (preciseCheck(nodes[i], clientPos.x, clientPos.y)) { - return nodes[i].node; - } - } - return null; - } - }; - - // Let graphics fire events before we return it to the caller. - eventify(graphics); - - return graphics; -} +var eventify = require('ngraph.events'); +var forceDirected = require('ngraph.forcelayout'); +var svgGraphics = require('./svgGraphics.js'); +var windowEvents = require('../Utils/windowEvents.js'); +var domInputManager = require('../Input/domInputManager.js'); +var timer = require('../Utils/timer.js'); +var getDimension = require('../Utils/getDimensions.js'); +var dragndrop = require('../Input/dragndrop.js'); -},{"../Input/webglInputManager.js":36,"../WebGL/webglLine.js":58,"../WebGL/webglLinkProgram.js":59,"../WebGL/webglNodeProgram.js":60,"../WebGL/webglSquare.js":61,"ngraph.events":7,"ngraph.merge":13}],51:[function(require,module,exports){ -module.exports = parseColor; +/** + * This is heart of the rendering. Class accepts graph to be rendered and rendering settings. + * It monitors graph changes and depicts them accordingly. + * + * @param graph - Viva.Graph.graph() object to be rendered. + * @param settings - rendering settings, composed from the following parts (with their defaults shown): + * settings = { + * // Represents a module that is capable of displaying graph nodes and links. + * // all graphics has to correspond to defined interface and can be later easily + * // replaced for specific needs (e.g. adding WebGL should be piece of cake as long + * // as WebGL has implemented required interface). See svgGraphics for example. + * graphics : Viva.Graph.View.svgGraphics(), + * + * // Where the renderer should draw graph. Container size matters, because + * // renderer will attempt center graph to that size. Also graphics modules + * // might depend on it. + * container : document.body, + * + * // Defines whether graph can respond to use input + * interactive: true, + * + * // Layout algorithm to be used. The algorithm is expected to comply with defined + * // interface and is expected to be iterative. Renderer will use it then to calculate + * // grpaph's layout. For examples of the interface refer to Viva.Graph.Layout.forceDirected() + * layout : Viva.Graph.Layout.forceDirected(), + * + * // Directs renderer to display links. Usually rendering links is the slowest part of this + * // library. So if you don't need to display links, consider settings this property to false. + * renderLinks : true, + * + * // Number of layout iterations to run before displaying the graph. The bigger you set this number + * // the closer to ideal position graph will appear first time. But be careful: for large graphs + * // it can freeze the browser. + * prerender : 0 + * } + */ +function renderer(graph, settings) { + // TODO: This class is getting hard to understand. Consider refactoring. + // TODO: I have a technical debt here: fix scaling/recentering! Currently it's a total mess. + var FRAME_INTERVAL = 30; + + settings = settings || {}; + + var layout = settings.layout, + graphics = settings.graphics, + container = settings.container, + interactive = settings.interactive !== undefined ? settings.interactive : true, + inputManager, + animationTimer, + rendererInitialized = false, + updateCenterRequired = true, + + currentStep = 0, + totalIterationsCount = 0, + isStable = false, + userInteraction = false, + isPaused = false, + + transform = { + offsetX: 0, + offsetY: 0, + scale: 1 + }, -function parseColor(color) { - var parsedColor = 0x009ee8ff; + publicEvents = eventify({}), + containerDrag; - if (typeof color === 'string' && color) { - if (color.length === 4) { // #rgb - color = color.replace(/([^#])/g, '$1$1'); // duplicate each letter except first #. - } - if (color.length === 9) { // #rrggbbaa - parsedColor = parseInt(color.substr(1), 16); - } else if (color.length === 7) { // or #rrggbb. - parsedColor = (parseInt(color.substr(1), 16) << 8) | 0xff; - } else { - throw 'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: ' + color; - } - } else if (typeof color === 'number') { - parsedColor = color; - } + return { + /** + * Performs rendering of the graph. + * + * @param iterationsCount if specified renderer will run only given number of iterations + * and then stop. Otherwise graph rendering is performed infinitely. + * + * Note: if rendering stopped by used started dragging nodes or new nodes were added to the + * graph renderer will give run more iterations to reflect changes. + */ + run: function(iterationsCount) { - return parsedColor; -} + if (!rendererInitialized) { + prepareSettings(); + prerender(); -},{}],52:[function(require,module,exports){ -module.exports = Texture; + initDom(); + updateCenter(); + listenToEvents(); -/** - * Single texture in the webglAtlas. - */ -function Texture(size) { - this.canvas = window.document.createElement("canvas"); - this.ctx = this.canvas.getContext("2d"); - this.isDirty = false; - this.canvas.width = this.canvas.height = size; -} + rendererInitialized = true; + } -},{}],53:[function(require,module,exports){ -/** - * @fileOverview Utility functions for webgl rendering. - * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com - */ + renderIterations(iterationsCount); -module.exports = webgl; + return this; + }, -function webgl(gl) { + reset: function() { + graphics.resetScale(); + updateCenter(); + transform.scale = 1; + }, - return { - createProgram: createProgram, - extendArray: extendArray, - copyArrayPart: copyArrayPart, - swapArrayPart: swapArrayPart, - getLocations: getLocations, - context: gl - }; + pause: function() { + isPaused = true; + animationTimer.stop(); + }, - function createShader(shaderText, type) { - var shader = gl.createShader(type); - gl.shaderSource(shader, shaderText); - gl.compileShader(shader); + resume: function() { + isPaused = false; + animationTimer.restart(); + }, - if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { - var msg = gl.getShaderInfoLog(shader); - window.alert(msg); - throw msg; - } + rerender: function() { + renderGraph(); + return this; + }, - return shader; - } + zoomOut: function() { + return scale(true); + }, - function createProgram(vertexShaderSrc, fragmentShaderSrc) { - var program = gl.createProgram(); - var vs = createShader(vertexShaderSrc, gl.VERTEX_SHADER); - var fs = createShader(fragmentShaderSrc, gl.FRAGMENT_SHADER); + zoomIn: function() { + return scale(false); + }, - gl.attachShader(program, vs); - gl.attachShader(program, fs); - gl.linkProgram(program); + /** + * Centers renderer at x,y graph's coordinates + */ + moveTo: function(x, y) { + graphics.graphCenterChanged(transform.offsetX - x * transform.scale, transform.offsetY - y * transform.scale); + renderGraph(); + }, - if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { - var msg = gl.getShaderInfoLog(program); - window.alert(msg); - throw msg; + /** + * Gets current graphics object + */ + getGraphics: function() { + return graphics; + }, + + /** + * Removes this renderer and deallocates all resources/timers + */ + dispose: function() { + stopListenToEvents(); // I quit! + }, + + on: function(eventName, callback) { + publicEvents.on(eventName, callback); + return this; + }, + + off: function(eventName, callback) { + publicEvents.off(eventName, callback); + return this; } + }; - return program; + /** + * Checks whether given interaction (node/scroll) is enabled + */ + function isInteractive(interactionName) { + if (typeof interactive === 'string') { + return interactive.indexOf(interactionName) >= 0; + } else if (typeof interactive === 'boolean') { + return interactive; + } + return true; // default setting } - function extendArray(buffer, itemsInBuffer, elementsPerItem) { - if ((itemsInBuffer + 1) * elementsPerItem > buffer.length) { - // Every time we run out of space create new array twice bigger. - // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs - var extendedArray = new Float32Array(buffer.length * elementsPerItem * 2); - extendedArray.set(buffer); + function prepareSettings() { + container = container || window.document.body; + layout = layout || forceDirected(graph, { + springLength: 80, + springCoeff: 0.0002, + }); + graphics = graphics || svgGraphics(graph, { + container: container + }); - return extendedArray; + if (!settings.hasOwnProperty('renderLinks')) { + settings.renderLinks = true; } - return buffer; + settings.prerender = settings.prerender || 0; + inputManager = (graphics.inputManager || domInputManager)(graph, graphics); } - function getLocations(program, uniformOrAttributeNames) { - var foundLocations = {}; - for (var i = 0; i < uniformOrAttributeNames.length; ++i) { - var name = uniformOrAttributeNames[i]; - var location = -1; - if (name[0] === 'a' && name[1] === '_') { - location = gl.getAttribLocation(program, name); - if (location === -1) { - throw new Error("Program doesn't have required attribute: " + name); - } - - foundLocations[name.slice(2)] = location; - } else if (name[0] === 'u' && name[1] === '_') { - location = gl.getUniformLocation(program, name); - if (location === null) { - throw new Error("Program doesn't have required uniform: " + name); - } + function renderGraph() { + graphics.beginRender(); - foundLocations[name.slice(2)] = location; - } else { - throw new Error("Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'"); - } + // todo: move this check graphics + if (settings.renderLinks) { + graphics.renderLinks(); } - - return foundLocations; + graphics.renderNodes(); + graphics.endRender(); } -} -function copyArrayPart(array, to, from, elementsCount) { - for (var i = 0; i < elementsCount; ++i) { - array[to + i] = array[from + i]; + function onRenderFrame() { + isStable = layout.step() && !userInteraction; + renderGraph(); + + return !isStable; } -} -function swapArrayPart(array, from, to, elementsCount) { - for (var i = 0; i < elementsCount; ++i) { - var tmp = array[from + i]; + function renderIterations(iterationsCount) { + if (animationTimer) { + totalIterationsCount += iterationsCount; + return; + } + + if (iterationsCount) { + totalIterationsCount += iterationsCount; + + animationTimer = timer(function() { + return onRenderFrame(); + }, FRAME_INTERVAL); + } else { + currentStep = 0; + totalIterationsCount = 0; + animationTimer = timer(onRenderFrame, FRAME_INTERVAL); + } + } + + function resetStable() { + if (isPaused) { + return; + } + + isStable = false; + animationTimer.restart(); + } + + function prerender() { + // To get good initial positions for the graph + // perform several prerender steps in background. + if (typeof settings.prerender === 'number' && settings.prerender > 0) { + for (var i = 0; i < settings.prerender; i += 1) { + layout.step(); + } + } + } + + function updateCenter() { + var graphRect = layout.getGraphRect(), + containerSize = getDimension(container); + + var cx = (graphRect.x2 + graphRect.x1) / 2; + var cy = (graphRect.y2 + graphRect.y1) / 2; + transform.offsetX = containerSize.width / 2 - (cx * transform.scale - cx); + transform.offsetY = containerSize.height / 2 - (cy * transform.scale - cy); + graphics.graphCenterChanged(transform.offsetX, transform.offsetY); + + updateCenterRequired = false; + } + + function createNodeUi(node) { + var nodePosition = layout.getNodePosition(node.id); + graphics.addNode(node, nodePosition); + } + + function removeNodeUi(node) { + graphics.releaseNode(node); + } + + function createLinkUi(link) { + var linkPosition = layout.getLinkPosition(link.id); + graphics.addLink(link, linkPosition); + } + + function removeLinkUi(link) { + graphics.releaseLink(link); + } + + function listenNodeEvents(node) { + if (!isInteractive('node')) { + return; + } + + var wasPinned = false; + + // TODO: This may not be memory efficient. Consider reusing handlers object. + inputManager.bindDragNDrop(node, { + onStart: function() { + wasPinned = layout.isNodePinned(node); + layout.pinNode(node, true); + userInteraction = true; + resetStable(); + }, + onDrag: function(e, offset) { + var oldPos = layout.getNodePosition(node.id); + layout.setNodePosition(node.id, + oldPos.x + offset.x / transform.scale, + oldPos.y + offset.y / transform.scale); + + userInteraction = true; + + renderGraph(); + }, + onStop: function() { + layout.pinNode(node, wasPinned); + userInteraction = false; + } + }); + } + + function releaseNodeEvents(node) { + inputManager.bindDragNDrop(node, null); + } + + function initDom() { + graphics.init(container); + + graph.forEachNode(createNodeUi); + + if (settings.renderLinks) { + graph.forEachLink(createLinkUi); + } + } + + function releaseDom() { + graphics.release(container); + } + + function processNodeChange(change) { + var node = change.node; + + if (change.changeType === 'add') { + createNodeUi(node); + listenNodeEvents(node); + if (updateCenterRequired) { + updateCenter(); + } + } else if (change.changeType === 'remove') { + releaseNodeEvents(node); + removeNodeUi(node); + if (graph.getNodesCount() === 0) { + updateCenterRequired = true; // Next time when node is added - center the graph. + } + } else if (change.changeType === 'update') { + releaseNodeEvents(node); + removeNodeUi(node); + + createNodeUi(node); + listenNodeEvents(node); + } + } + + function processLinkChange(change) { + var link = change.link; + if (change.changeType === 'add') { + if (settings.renderLinks) { + createLinkUi(link); + } + } else if (change.changeType === 'remove') { + if (settings.renderLinks) { + removeLinkUi(link); + } + } else if (change.changeType === 'update') { + throw 'Update type is not implemented. TODO: Implement me!'; + } + } + + function onGraphChanged(changes) { + var i, change; + for (i = 0; i < changes.length; i += 1) { + change = changes[i]; + if (change.node) { + processNodeChange(change); + } else if (change.link) { + processLinkChange(change); + } + } + + resetStable(); + } + + function onWindowResized() { + updateCenter(); + onRenderFrame(); + } + + function releaseContainerDragManager() { + if (containerDrag) { + containerDrag.release(); + containerDrag = null; + } + } + + function releaseGraphEvents() { + graph.off('changed', onGraphChanged); + } + + function scale(out, scrollPoint) { + if (!scrollPoint) { + var containerSize = getDimension(container); + scrollPoint = { + x: containerSize.width / 2, + y: containerSize.height / 2 + }; + } + var scaleFactor = Math.pow(1 + 0.4, out ? -0.2 : 0.2); + transform.scale = graphics.scale(scaleFactor, scrollPoint); + + renderGraph(); + publicEvents.fire('scale', transform.scale); + + return transform.scale; + } + + function listenToEvents() { + windowEvents.on('resize', onWindowResized); + + releaseContainerDragManager(); + if (isInteractive('drag')) { + containerDrag = dragndrop(container); + containerDrag.onDrag(function(e, offset) { + graphics.translateRel(offset.x, offset.y); + + renderGraph(); + publicEvents.fire('drag', offset); + }); + } + + if (isInteractive('scroll')) { + if (!containerDrag) { + containerDrag = dragndrop(container); + } + containerDrag.onScroll(function(e, scaleOffset, scrollPoint) { + scale(scaleOffset < 0, scrollPoint); + }); + } + + graph.forEachNode(listenNodeEvents); + + releaseGraphEvents(); + graph.on('changed', onGraphChanged); + } + + function stopListenToEvents() { + rendererInitialized = false; + releaseGraphEvents(); + releaseContainerDragManager(); + windowEvents.off('resize', onWindowResized); + publicEvents.off(); + animationTimer.stop(); + + graph.forEachLink(function(link) { + if (settings.renderLinks) { + removeLinkUi(link); + } + }); + + graph.forEachNode(function(node) { + releaseNodeEvents(node); + removeNodeUi(node); + }); + + layout.dispose(); + releaseDom(); + } +} + +},{"../Input/domInputManager.js":34,"../Input/dragndrop.js":35,"../Utils/getDimensions.js":42,"../Utils/timer.js":46,"../Utils/windowEvents.js":47,"./svgGraphics.js":49,"ngraph.events":7,"ngraph.forcelayout":9}],49:[function(require,module,exports){ +/** + * @fileOverview Defines a graph renderer that uses SVG based drawings. + * + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka + */ + +module.exports = svgGraphics; + +var svg = require('simplesvg'); +var eventify = require('ngraph.events'); +var domInputManager = require('../Input/domInputManager.js'); + +/** + * Performs svg-based graph rendering. This module does not perform + * layout, but only visualizes nodes and edges of the graph. + */ +function svgGraphics() { + var svgContainer, + svgRoot, + offsetX = 0, + offsetY = 0, + initCallback, + actualScale = 1, + allNodes = {}, + allLinks = {}, +/*jshint unused: false */ + nodeBuilder = function (node) { + return svg("rect") + .attr("width", 10) + .attr("height", 10) + .attr("fill", "#00a2e8"); + }, + + nodePositionCallback = function (nodeUI, pos) { + // TODO: Remove magic 5. It should be half of the width or height of the node. + nodeUI.attr("x", pos.x - 5) + .attr("y", pos.y - 5); + }, + + linkBuilder = function (link) { + return svg("line").attr("stroke", "#999"); + }, + + linkPositionCallback = function (linkUI, fromPos, toPos) { + linkUI.attr("x1", fromPos.x) + .attr("y1", fromPos.y) + .attr("x2", toPos.x) + .attr("y2", toPos.y); + }, + + fireRescaled = function (graphics) { + // TODO: maybe we shall copy changes? + graphics.fire("rescaled"); + }, + + cachedPos = {x : 0, y: 0}, + cachedFromPos = {x : 0, y: 0}, + cachedToPos = {x : 0, y: 0}, + + updateTransform = function () { + if (svgContainer) { + var transform = "matrix(" + actualScale + ", 0, 0," + actualScale + "," + offsetX + "," + offsetY + ")"; + svgContainer.attr("transform", transform); + } + }; + + svgRoot = createSvgRoot(); + + var graphics = { + getNodeUI: function (nodeId) { + return allNodes[nodeId]; + }, + + getLinkUI: function (linkId) { + return allLinks[linkId]; + }, + + /** + * Sets the callback that creates node representation. + * + * @param builderCallback a callback function that accepts graph node + * as a parameter and must return an element representing this node. + * + * @returns If builderCallbackOrNode is a valid callback function, instance of this is returned; + * Otherwise undefined value is returned + */ + node : function (builderCallback) { + if (typeof builderCallback !== "function") { + return; // todo: throw? This is not compatible with old versions + } + + nodeBuilder = builderCallback; + + return this; + }, + + /** + * Sets the callback that creates link representation + * + * @param builderCallback a callback function that accepts graph link + * as a parameter and must return an element representing this link. + * + * @returns If builderCallback is a valid callback function, instance of this is returned; + * Otherwise undefined value is returned. + */ + link : function (builderCallback) { + if (typeof builderCallback !== "function") { + return; // todo: throw? This is not compatible with old versions + } + + linkBuilder = builderCallback; + return this; + }, + + /** + * Allows to override default position setter for the node with a new + * function. newPlaceCallback(nodeUI, position, node) is function which + * is used by updateNodePosition(). + */ + placeNode : function (newPlaceCallback) { + nodePositionCallback = newPlaceCallback; + return this; + }, + + placeLink : function (newPlaceLinkCallback) { + linkPositionCallback = newPlaceLinkCallback; + return this; + }, + + /** + * Called every before renderer starts rendering. + */ + beginRender : function () {}, + + /** + * Called every time when renderer finishes one step of rendering. + */ + endRender : function () {}, + + /** + * Sets translate operation that should be applied to all nodes and links. + */ + graphCenterChanged : function (x, y) { + offsetX = x; + offsetY = y; + updateTransform(); + }, + + /** + * Default input manager listens to DOM events to process nodes drag-n-drop + */ + inputManager : domInputManager, + + translateRel : function (dx, dy) { + var p = svgRoot.createSVGPoint(), + t = svgContainer.getCTM(), + origin = svgRoot.createSVGPoint().matrixTransform(t.inverse()); + + p.x = dx; + p.y = dy; + + p = p.matrixTransform(t.inverse()); + p.x = (p.x - origin.x) * t.a; + p.y = (p.y - origin.y) * t.d; + + t.e += p.x; + t.f += p.y; + + var transform = "matrix(" + t.a + ", 0, 0," + t.d + "," + t.e + "," + t.f + ")"; + svgContainer.attr("transform", transform); + }, + + scale : function (scaleFactor, scrollPoint) { + var p = svgRoot.createSVGPoint(); + p.x = scrollPoint.x; + p.y = scrollPoint.y; + + p = p.matrixTransform(svgContainer.getCTM().inverse()); // translate to SVG coordinates + + // Compute new scale matrix in current mouse position + var k = svgRoot.createSVGMatrix().translate(p.x, p.y).scale(scaleFactor).translate(-p.x, -p.y), + t = svgContainer.getCTM().multiply(k); + + actualScale = t.a; + offsetX = t.e; + offsetY = t.f; + var transform = "matrix(" + t.a + ", 0, 0," + t.d + "," + t.e + "," + t.f + ")"; + svgContainer.attr("transform", transform); + + fireRescaled(this); + return actualScale; + }, + + resetScale : function () { + actualScale = 1; + var transform = "matrix(1, 0, 0, 1, 0, 0)"; + svgContainer.attr("transform", transform); + fireRescaled(this); + return this; + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render. + */ + init : function (container) { + container.appendChild(svgRoot); + updateTransform(); + // Notify the world if someone waited for update. TODO: should send an event + if (typeof initCallback === "function") { + initCallback(svgRoot); + } + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider release occupied resources. + */ + release : function (container) { + if (svgRoot && container) { + container.removeChild(svgRoot); + } + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render given link of the graph + * + * @param link - model of a link + */ + addLink: function (link, pos) { + var linkUI = linkBuilder(link); + if (!linkUI) { return; } + linkUI.position = pos; + linkUI.link = link; + allLinks[link.id] = linkUI; + if (svgContainer.childElementCount > 0) { + svgContainer.insertBefore(linkUI, svgContainer.firstChild); + } else { + svgContainer.appendChild(linkUI); + } + return linkUI; + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider remove link from rendering surface. + * + * @param linkUI visual representation of the link created by link() execution. + **/ + releaseLink : function (link) { + var linkUI = allLinks[link.id]; + if (linkUI) { + svgContainer.removeChild(linkUI); + delete allLinks[link.id]; + } + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render given node of the graph. + * + * @param nodeUI visual representation of the node created by node() execution. + **/ + addNode : function (node, pos) { + var nodeUI = nodeBuilder(node); + if (!nodeUI) { + return; + } + nodeUI.position = pos; + nodeUI.node = node; + allNodes[node.id] = nodeUI; + + svgContainer.appendChild(nodeUI); + + return nodeUI; + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider remove node from rendering surface. + * + * @param node graph's node + **/ + releaseNode : function (node) { + var nodeUI = allNodes[node.id]; + if (nodeUI) { + svgContainer.removeChild(nodeUI); + delete allNodes[node.id]; + } + }, + + renderNodes : function () { + for (var key in allNodes) { + if (allNodes.hasOwnProperty(key)) { + var nodeUI = allNodes[key]; + cachedPos.x = nodeUI.position.x; + cachedPos.y = nodeUI.position.y; + nodePositionCallback(nodeUI, cachedPos, nodeUI.node); + } + } + }, + + renderLinks : function () { + for (var key in allLinks) { + if (allLinks.hasOwnProperty(key)) { + var linkUI = allLinks[key]; + cachedFromPos.x = linkUI.position.from.x; + cachedFromPos.y = linkUI.position.from.y; + cachedToPos.x = linkUI.position.to.x; + cachedToPos.y = linkUI.position.to.y; + linkPositionCallback(linkUI, cachedFromPos, cachedToPos, linkUI.link); + } + } + }, + + /** + * Returns root element which hosts graphics. + */ + getGraphicsRoot : function (callbackWhenReady) { + // todo: should fire an event, instead of having this context. + if (typeof callbackWhenReady === "function") { + if (svgRoot) { + callbackWhenReady(svgRoot); + } else { + initCallback = callbackWhenReady; + } + } + return svgRoot; + }, + /** + * Returns root SVG element. + * + * Note: This is internal method specific to this renderer + */ + getSvgRoot : function () { + return svgRoot; + } + }; + + + // Let graphics fire events before we return it to the caller. + eventify(graphics); + + return graphics; + + function createSvgRoot() { + var svgRoot = svg("svg"); + + svgContainer = svg("g") + .attr("buffered-rendering", "dynamic"); + + svgRoot.appendChild(svgContainer); + return svgRoot; + } +} + +},{"../Input/domInputManager.js":34,"ngraph.events":7,"simplesvg":28}],50:[function(require,module,exports){ +/** + * @fileOverview Defines a graph renderer that uses WebGL based drawings. + * + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka + */ + +module.exports = webglGraphics; + +var webglInputManager = require('../Input/webglInputManager.js'); +var webglLinkProgram = require('../WebGL/webglLinkProgram.js'); +var webglNodeProgram = require('../WebGL/webglNodeProgram.js'); +var webglSquare = require('../WebGL/webglSquare.js'); +var webglLine = require('../WebGL/webglLine.js'); +var eventify = require('ngraph.events'); +var merge = require('ngraph.merge'); + +/** + * Performs webgl-based graph rendering. This module does not perform + * layout, but only visualizes nodes and edges of the graph. + * + * @param options - to customize graphics behavior. Currently supported parameter + * enableBlending - true by default, allows to use transparency in node/links colors. + * preserveDrawingBuffer - false by default, tells webgl to preserve drawing buffer. + * See https://www.khronos.org/registry/webgl/specs/1.0/#5.2 + */ + +function webglGraphics(options) { + options = merge(options, { + enableBlending : true, + preserveDrawingBuffer : false, + clearColor: false, + clearColorValue : { + r : 1, + g : 1, + b : 1, + a : 1 + } + }); + + var container, + graphicsRoot, + gl, + width, + height, + nodesCount = 0, + linksCount = 0, + transform = [ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + ], + userPlaceNodeCallback, + userPlaceLinkCallback, + nodes = [], + links = [], + initCallback, + + allNodes = {}, + allLinks = {}, + linkProgram = webglLinkProgram(), + nodeProgram = webglNodeProgram(), +/*jshint unused: false */ + nodeUIBuilder = function (node) { + return webglSquare(); // Just make a square, using provided gl context (a nodeProgram); + }, + + linkUIBuilder = function (link) { + return webglLine(0xb3b3b3ff); + }, +/*jshint unused: true */ + updateTransformUniform = function () { + linkProgram.updateTransform(transform); + nodeProgram.updateTransform(transform); + }, + + resetScaleInternal = function () { + transform = [1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]; + }, + + updateSize = function () { + if (container && graphicsRoot) { + width = graphicsRoot.width = Math.max(container.offsetWidth, 1); + height = graphicsRoot.height = Math.max(container.offsetHeight, 1); + if (gl) { gl.viewport(0, 0, width, height); } + if (linkProgram) { linkProgram.updateSize(width / 2, height / 2); } + if (nodeProgram) { nodeProgram.updateSize(width / 2, height / 2); } + } + }, + + fireRescaled = function (graphics) { + graphics.fire("rescaled"); + }; + + graphicsRoot = window.document.createElement("canvas"); + + var graphics = { + getLinkUI: function (linkId) { + return allLinks[linkId]; + }, + + getNodeUI: function (nodeId) { + return allNodes[nodeId]; + }, + + /** + * Sets the callback that creates node representation. + * + * @param builderCallback a callback function that accepts graph node + * as a parameter and must return an element representing this node. + * + * @returns If builderCallbackOrNode is a valid callback function, instance of this is returned; + * Otherwise undefined value is returned + */ + node : function (builderCallback) { + if (typeof builderCallback !== "function") { + return; // todo: throw? This is not compatible with old versions + } + + nodeUIBuilder = builderCallback; + + return this; + }, + + /** + * Sets the callback that creates link representation + * + * @param builderCallback a callback function that accepts graph link + * as a parameter and must return an element representing this link. + * + * @returns If builderCallback is a valid callback function, instance of this is returned; + * Otherwise undefined value is returned. + */ + link : function (builderCallback) { + if (typeof builderCallback !== "function") { + return; // todo: throw? This is not compatible with old versions + } + + linkUIBuilder = builderCallback; + return this; + }, + + + /** + * Allows to override default position setter for the node with a new + * function. newPlaceCallback(nodeUI, position) is function which + * is used by updateNodePosition(). + */ + placeNode : function (newPlaceCallback) { + userPlaceNodeCallback = newPlaceCallback; + return this; + }, + + placeLink : function (newPlaceLinkCallback) { + userPlaceLinkCallback = newPlaceLinkCallback; + return this; + }, + + /** + * Custom input manager listens to mouse events to process nodes drag-n-drop inside WebGL canvas + */ + inputManager : webglInputManager, + + /** + * Called every time before renderer starts rendering. + */ + beginRender : function () { + // this function could be replaced by this.init, + // based on user options. + }, + + /** + * Called every time when renderer finishes one step of rendering. + */ + endRender : function () { + if (linksCount > 0) { + linkProgram.render(); + } + if (nodesCount > 0) { + nodeProgram.render(); + } + }, + + bringLinkToFront : function (linkUI) { + var frontLinkId = linkProgram.getFrontLinkId(), + srcLinkId, + temp; + + linkProgram.bringToFront(linkUI); + + if (frontLinkId > linkUI.id) { + srcLinkId = linkUI.id; + + temp = links[frontLinkId]; + links[frontLinkId] = links[srcLinkId]; + links[frontLinkId].id = frontLinkId; + links[srcLinkId] = temp; + links[srcLinkId].id = srcLinkId; + } + }, + + /** + * Sets translate operation that should be applied to all nodes and links. + */ + graphCenterChanged : function (x, y) { + transform[12] = (2 * x / width) - 1; + transform[13] = 1 - (2 * y / height); + updateTransformUniform(); + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render given link of the graph + * + * @param link - model of a link + */ + addLink: function (link, boundPosition) { + var uiid = linksCount++, + ui = linkUIBuilder(link); + ui.id = uiid; + ui.pos = boundPosition; + + linkProgram.createLink(ui); + + links[uiid] = ui; + allLinks[link.id] = ui; + return ui; + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render given node of the graph. + * + * @param nodeUI visual representation of the node created by node() execution. + **/ + addNode : function (node, boundPosition) { + var uiid = nodesCount++, + ui = nodeUIBuilder(node); + + ui.id = uiid; + ui.position = boundPosition; + ui.node = node; + + nodeProgram.createNode(ui); + + nodes[uiid] = ui; + allNodes[node.id] = ui; + return ui; + }, + + translateRel : function (dx, dy) { + transform[12] += (2 * transform[0] * dx / width) / transform[0]; + transform[13] -= (2 * transform[5] * dy / height) / transform[5]; + updateTransformUniform(); + }, + + scale : function (scaleFactor, scrollPoint) { + // Transform scroll point to clip-space coordinates: + var cx = 2 * scrollPoint.x / width - 1, + cy = 1 - (2 * scrollPoint.y) / height; + + cx -= transform[12]; + cy -= transform[13]; + + transform[12] += cx * (1 - scaleFactor); + transform[13] += cy * (1 - scaleFactor); + + transform[0] *= scaleFactor; + transform[5] *= scaleFactor; + + updateTransformUniform(); + fireRescaled(this); + + return transform[0]; + }, + + resetScale : function () { + resetScaleInternal(); + + if (gl) { + updateSize(); + // TODO: what is this? + // gl.useProgram(linksProgram); + // gl.uniform2f(linksProgram.screenSize, width, height); + updateTransformUniform(); + } + return this; + }, + + /** + * Resizes the graphic without resetting the scale. + * Useful with viva graph in a dynamic container + */ + updateSize: updateSize, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render. + */ + init : function (c) { + var contextParameters = {}; + + if (options.preserveDrawingBuffer) { + contextParameters.preserveDrawingBuffer = true; + } + + container = c; + + updateSize(); + resetScaleInternal(); + container.appendChild(graphicsRoot); + + + gl = graphicsRoot.getContext("experimental-webgl", contextParameters); + if (!gl) { + var msg = "Could not initialize WebGL. Seems like the browser doesn't support it."; + window.alert(msg); + throw msg; + } + if (options.enableBlending) { + gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); + gl.enable(gl.BLEND); + } + if (options.clearColor) { + var color = options.clearColorValue; + gl.clearColor(color.r, color.g, color.b, color.a); + // TODO: not the best way, really. Should come up with something better + // what if we need more updates inside beginRender, like depth buffer? + this.beginRender = function () { + gl.clear(gl.COLOR_BUFFER_BIT); + }; + } + + linkProgram.load(gl); + linkProgram.updateSize(width / 2, height / 2); + + nodeProgram.load(gl); + nodeProgram.updateSize(width / 2, height / 2); + + updateTransformUniform(); + + // Notify the world if someone waited for update. TODO: should send an event + if (typeof initCallback === "function") { + initCallback(graphicsRoot); + } + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider release occupied resources. + */ + release : function (container) { + if (graphicsRoot && container) { + container.removeChild(graphicsRoot); + // TODO: anything else? + } + }, + + /** + * Checks whether webgl is supported by this browser. + */ + isSupported : function () { + var c = window.document.createElement("canvas"), + gl = c && c.getContext && c.getContext("experimental-webgl"); + return gl; + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider remove link from rendering surface. + * + * @param linkUI visual representation of the link created by link() execution. + **/ + releaseLink : function (link) { + if (linksCount > 0) { linksCount -= 1; } + var linkUI = allLinks[link.id]; + delete allLinks[link.id]; + + linkProgram.removeLink(linkUI); + + var linkIdToRemove = linkUI.id; + if (linkIdToRemove < linksCount) { + if (linksCount === 0 || linksCount === linkIdToRemove) { + return; // no more links or removed link is the last one. + } + + var lastLinkUI = links[linksCount]; + links[linkIdToRemove] = lastLinkUI; + lastLinkUI.id = linkIdToRemove; + } + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider remove node from rendering surface. + * + * @param nodeUI visual representation of the node created by node() execution. + **/ + releaseNode : function (node) { + if (nodesCount > 0) { nodesCount -= 1; } + var nodeUI = allNodes[node.id]; + delete allNodes[node.id]; + + nodeProgram.removeNode(nodeUI); + + var nodeIdToRemove = nodeUI.id; + if (nodeIdToRemove < nodesCount) { + if (nodesCount === 0 || nodesCount === nodeIdToRemove) { + return; // no more nodes or removed node is the last in the list. + } + + var lastNodeUI = nodes[nodesCount]; + + nodes[nodeIdToRemove] = lastNodeUI; + lastNodeUI.id = nodeIdToRemove; + + // Since concrete shaders may cache properties in the UI element + // we are letting them to make this swap (e.g. image node shader + // uses this approach to update node's offset in the atlas) + nodeProgram.replaceProperties(nodeUI, lastNodeUI); + } + }, + + renderNodes: function () { + var pos = {x : 0, y : 0}; + // WebGL coordinate system is different. Would be better + // to have this transform in the shader code, but it would + // require every shader to be updated.. + for (var i = 0; i < nodesCount; ++i) { + var ui = nodes[i]; + pos.x = ui.position.x; + pos.y = ui.position.y; + if (userPlaceNodeCallback) { + userPlaceNodeCallback(ui, pos); + } + + nodeProgram.position(ui, pos); + } + }, + + renderLinks: function () { + if (this.omitLinksRendering) { return; } + + var toPos = {x : 0, y : 0}; + var fromPos = {x : 0, y : 0}; + for (var i = 0; i < linksCount; ++i) { + var ui = links[i]; + var pos = ui.pos.from; + fromPos.x = pos.x; + fromPos.y = -pos.y; + pos = ui.pos.to; + toPos.x = pos.x; + toPos.y = -pos.y; + if (userPlaceLinkCallback) { + userPlaceLinkCallback(ui, fromPos, toPos); + } + + linkProgram.position(ui, fromPos, toPos); + } + }, + + /** + * Returns root element which hosts graphics. + */ + getGraphicsRoot : function (callbackWhenReady) { + // todo: should fire an event, instead of having this context. + if (typeof callbackWhenReady === "function") { + if (graphicsRoot) { + callbackWhenReady(graphicsRoot); + } else { + initCallback = callbackWhenReady; + } + } + return graphicsRoot; + }, + + /** + * Updates default shader which renders nodes + * + * @param newProgram to use for nodes. + */ + setNodeProgram : function (newProgram) { + if (!gl && newProgram) { + // Nothing created yet. Just set shader to the new one + // and let initialization logic take care about the rest. + nodeProgram = newProgram; + } else if (newProgram) { + throw "Not implemented. Cannot swap shader on the fly... Yet."; + // TODO: unload old shader and reinit. + } + }, + + /** + * Updates default shader which renders links + * + * @param newProgram to use for links. + */ + setLinkProgram : function (newProgram) { + if (!gl && newProgram) { + // Nothing created yet. Just set shader to the new one + // and let initialization logic take care about the rest. + linkProgram = newProgram; + } else if (newProgram) { + throw "Not implemented. Cannot swap shader on the fly... Yet."; + // TODO: unload old shader and reinit. + } + }, + + /** + * Transforms client coordinates into layout coordinates. Client coordinates + * are DOM coordinates relative to the rendering container. Layout + * coordinates are those assigned by by layout algorithm to each node. + * + * @param {Object} p - a point object with `x` and `y` attributes. + * This method mutates p. + */ + transformClientToGraphCoordinates: function (p) { + // TODO: could be a problem when container has margins? + // normalize + p.x = ((2 * p.x) / width) - 1; + p.y = 1 - ((2 * p.y) / height); + + // apply transform + p.x = (p.x - transform[12]) / transform[0]; + p.y = (p.y - transform[13]) / transform[5]; + + // transform to graph coordinates + p.x = p.x * (width / 2); + p.y = p.y * (-height / 2); + + return p; + }, + + /** + * Transforms WebGL coordinates into client coordinates. Reverse of + * `transformClientToGraphCoordinates()` + * + * @param {Object} p - a point object with `x` and `y` attributes, which + * represents a layout coordinate. This method mutates p. + */ + transformGraphToClientCoordinates: function (p) { + // TODO: could be a problem when container has margins? + // transform from graph coordinates + p.x = p.x / (width / 2); + p.y = p.y / (-height / 2); + + // apply transform + p.x = (p.x * transform[0]) + transform[12]; + p.y = (p.y * transform[5]) + transform[13]; + + // denormalize + p.x = ((p.x + 1) * width) / 2; + p.y = ((1 - p.y) * height) / 2; + + return p; + }, + + getNodeAtClientPos: function (clientPos, preciseCheck) { + if (typeof preciseCheck !== "function") { + // we don't know anything about your node structure here :( + // potentially this could be delegated to node program, but for + // right now, we are giving up if you don't pass boundary check + // callback. It answers to a question is nodeUI covers (x, y) + return null; + } + // first transform to graph coordinates: + this.transformClientToGraphCoordinates(clientPos); + // now using precise check iterate over each node and find one within box: + // TODO: This is poor O(N) performance. + for (var i = 0; i < nodesCount; ++i) { + if (preciseCheck(nodes[i], clientPos.x, clientPos.y)) { + return nodes[i].node; + } + } + return null; + } + }; + + // Let graphics fire events before we return it to the caller. + eventify(graphics); + + return graphics; +} + +},{"../Input/webglInputManager.js":36,"../WebGL/webglLine.js":58,"../WebGL/webglLinkProgram.js":59,"../WebGL/webglNodeProgram.js":60,"../WebGL/webglSquare.js":61,"ngraph.events":7,"ngraph.merge":13}],51:[function(require,module,exports){ +module.exports = parseColor; + +function parseColor(color) { + var parsedColor = 0x009ee8ff; + + if (typeof color === 'string' && color) { + if (color.length === 4) { // #rgb + color = color.replace(/([^#])/g, '$1$1'); // duplicate each letter except first #. + } + if (color.length === 9) { // #rrggbbaa + parsedColor = parseInt(color.substr(1), 16); + } else if (color.length === 7) { // or #rrggbb. + parsedColor = (parseInt(color.substr(1), 16) << 8) | 0xff; + } else { + throw 'Color expected in hex format with preceding "#". E.g. #00ff00. Got value: ' + color; + } + } else if (typeof color === 'number') { + parsedColor = color; + } + + return parsedColor; +} + +},{}],52:[function(require,module,exports){ +module.exports = Texture; + +/** + * Single texture in the webglAtlas. + */ +function Texture(size) { + this.canvas = window.document.createElement("canvas"); + this.ctx = this.canvas.getContext("2d"); + this.isDirty = false; + this.canvas.width = this.canvas.height = size; +} + +},{}],53:[function(require,module,exports){ +/** + * @fileOverview Utility functions for webgl rendering. + * + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka + */ + +module.exports = webgl; + +function webgl(gl) { + + return { + createProgram: createProgram, + extendArray: extendArray, + copyArrayPart: copyArrayPart, + swapArrayPart: swapArrayPart, + getLocations: getLocations, + context: gl + }; + + function createShader(shaderText, type) { + var shader = gl.createShader(type); + gl.shaderSource(shader, shaderText); + gl.compileShader(shader); + + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + var msg = gl.getShaderInfoLog(shader); + window.alert(msg); + throw msg; + } + + return shader; + } + + function createProgram(vertexShaderSrc, fragmentShaderSrc) { + var program = gl.createProgram(); + var vs = createShader(vertexShaderSrc, gl.VERTEX_SHADER); + var fs = createShader(fragmentShaderSrc, gl.FRAGMENT_SHADER); + + gl.attachShader(program, vs); + gl.attachShader(program, fs); + gl.linkProgram(program); + + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { + var msg = gl.getShaderInfoLog(program); + window.alert(msg); + throw msg; + } + + return program; + } + + function extendArray(buffer, itemsInBuffer, elementsPerItem) { + if ((itemsInBuffer + 1) * elementsPerItem > buffer.length) { + // Every time we run out of space create new array twice bigger. + // TODO: it seems buffer size is limited. Consider using multiple arrays for huge graphs + var extendedArray = new Float32Array(buffer.length * elementsPerItem * 2); + extendedArray.set(buffer); + + return extendedArray; + } + + return buffer; + } + + function getLocations(program, uniformOrAttributeNames) { + var foundLocations = {}; + for (var i = 0; i < uniformOrAttributeNames.length; ++i) { + var name = uniformOrAttributeNames[i]; + var location = -1; + if (name[0] === 'a' && name[1] === '_') { + location = gl.getAttribLocation(program, name); + if (location === -1) { + throw new Error("Program doesn't have required attribute: " + name); + } + + foundLocations[name.slice(2)] = location; + } else if (name[0] === 'u' && name[1] === '_') { + location = gl.getUniformLocation(program, name); + if (location === null) { + throw new Error("Program doesn't have required uniform: " + name); + } + + foundLocations[name.slice(2)] = location; + } else { + throw new Error("Couldn't figure out your intent. All uniforms should start with 'u_' prefix, and attributes with 'a_'"); + } + } + + return foundLocations; + } +} + +function copyArrayPart(array, to, from, elementsCount) { + for (var i = 0; i < elementsCount; ++i) { + array[to + i] = array[from + i]; + } +} + +function swapArrayPart(array, from, to, elementsCount) { + for (var i = 0; i < elementsCount; ++i) { + var tmp = array[from + i]; array[from + i] = array[to + i]; array[to + i] = tmp; } @@ -6036,7 +6036,7 @@ function webglImage(size, src) { * @fileOverview Defines an image nodes for webglGraphics class. * Shape of nodes is square. * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ var WebglAtlas = require('./webglAtlas.js'); diff --git a/src/Utils/timer.js b/src/Utils/timer.js index 8e79c42..e4b8399 100644 --- a/src/Utils/timer.js +++ b/src/Utils/timer.js @@ -1,5 +1,5 @@ /** - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ module.exports = createTimer(); diff --git a/src/View/svgGraphics.js b/src/View/svgGraphics.js index df7ad4d..7dd77fc 100644 --- a/src/View/svgGraphics.js +++ b/src/View/svgGraphics.js @@ -1,7 +1,7 @@ /** * @fileOverview Defines a graph renderer that uses SVG based drawings. * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ module.exports = svgGraphics; diff --git a/src/WebGL/webgl.js b/src/WebGL/webgl.js index 94b8773..b9bea5d 100644 --- a/src/WebGL/webgl.js +++ b/src/WebGL/webgl.js @@ -1,7 +1,7 @@ /** * @fileOverview Utility functions for webgl rendering. * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ module.exports = webgl; diff --git a/src/WebGL/webglImageNodeProgram.js b/src/WebGL/webglImageNodeProgram.js index fc52020..59450d4 100644 --- a/src/WebGL/webglImageNodeProgram.js +++ b/src/WebGL/webglImageNodeProgram.js @@ -2,7 +2,7 @@ * @fileOverview Defines an image nodes for webglGraphics class. * Shape of nodes is square. * - * @author Andrei Kashcha (aka anvaka) / http://anvaka.blogspot.com + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ var WebglAtlas = require('./webglAtlas.js'); From 9d2f114046bd9fce4450425cfe6767b14e32c0c2 Mon Sep 17 00:00:00 2001 From: Andriy Kashcha Date: Thu, 1 Mar 2018 21:18:59 -0800 Subject: [PATCH 243/276] Fixed iterations count argument --- src/View/renderer.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/View/renderer.js b/src/View/renderer.js index 9d723f2..5a6baae 100644 --- a/src/View/renderer.js +++ b/src/View/renderer.js @@ -67,8 +67,6 @@ function renderer(graph, settings) { rendererInitialized = false, updateCenterRequired = true, - currentStep = 0, - totalIterationsCount = 0, isStable = false, userInteraction = false, isPaused = false, @@ -222,19 +220,20 @@ function renderer(graph, settings) { function renderIterations(iterationsCount) { if (animationTimer) { - totalIterationsCount += iterationsCount; return; } - if (iterationsCount) { - totalIterationsCount += iterationsCount; - + if (iterationsCount !== undefined) { animationTimer = timer(function() { + iterationsCount -= 1; + if (iterationsCount < 0) { + var needMoreFrames = false; + return needMoreFrames; + } + return onRenderFrame(); }, FRAME_INTERVAL); } else { - currentStep = 0; - totalIterationsCount = 0; animationTimer = timer(onRenderFrame, FRAME_INTERVAL); } } From 9d7ca9db57100c8a7ae0fff9e4d7c82807e4b430 Mon Sep 17 00:00:00 2001 From: Andriy Kashcha Date: Thu, 1 Mar 2018 21:20:23 -0800 Subject: [PATCH 244/276] Added getTransform Should help with https://github.com/anvaka/VivaGraphJS/issues/84#issuecomment-368608103 --- dist/vivagraph.js | 3418 +++++++++++++++++++++-------------------- dist/vivagraph.min.js | 2 +- src/View/renderer.js | 9 +- 3 files changed, 1721 insertions(+), 1708 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 0d0cf06..1217d7a 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -1,116 +1,116 @@ !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Viva=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= 0; - } else if (typeof interactive === 'boolean') { - return interactive; - } - return true; // default setting - } - - function prepareSettings() { - container = container || window.document.body; - layout = layout || forceDirected(graph, { - springLength: 80, - springCoeff: 0.0002, - }); - graphics = graphics || svgGraphics(graph, { - container: container - }); - - if (!settings.hasOwnProperty('renderLinks')) { - settings.renderLinks = true; - } - - settings.prerender = settings.prerender || 0; - inputManager = (graphics.inputManager || domInputManager)(graph, graphics); - } - - function renderGraph() { - graphics.beginRender(); - - // todo: move this check graphics - if (settings.renderLinks) { - graphics.renderLinks(); - } - graphics.renderNodes(); - graphics.endRender(); - } - - function onRenderFrame() { - isStable = layout.step() && !userInteraction; - renderGraph(); - - return !isStable; - } - - function renderIterations(iterationsCount) { - if (animationTimer) { - totalIterationsCount += iterationsCount; - return; - } - - if (iterationsCount) { - totalIterationsCount += iterationsCount; - - animationTimer = timer(function() { - return onRenderFrame(); - }, FRAME_INTERVAL); - } else { - currentStep = 0; - totalIterationsCount = 0; - animationTimer = timer(onRenderFrame, FRAME_INTERVAL); - } - } - - function resetStable() { - if (isPaused) { - return; - } - - isStable = false; - animationTimer.restart(); - } - - function prerender() { - // To get good initial positions for the graph - // perform several prerender steps in background. - if (typeof settings.prerender === 'number' && settings.prerender > 0) { - for (var i = 0; i < settings.prerender; i += 1) { - layout.step(); - } - } - } - - function updateCenter() { - var graphRect = layout.getGraphRect(), - containerSize = getDimension(container); - - var cx = (graphRect.x2 + graphRect.x1) / 2; - var cy = (graphRect.y2 + graphRect.y1) / 2; - transform.offsetX = containerSize.width / 2 - (cx * transform.scale - cx); - transform.offsetY = containerSize.height / 2 - (cy * transform.scale - cy); - graphics.graphCenterChanged(transform.offsetX, transform.offsetY); - - updateCenterRequired = false; - } - - function createNodeUi(node) { - var nodePosition = layout.getNodePosition(node.id); - graphics.addNode(node, nodePosition); - } - - function removeNodeUi(node) { - graphics.releaseNode(node); - } - - function createLinkUi(link) { - var linkPosition = layout.getLinkPosition(link.id); - graphics.addLink(link, linkPosition); - } - - function removeLinkUi(link) { - graphics.releaseLink(link); - } - - function listenNodeEvents(node) { - if (!isInteractive('node')) { - return; - } - - var wasPinned = false; - - // TODO: This may not be memory efficient. Consider reusing handlers object. - inputManager.bindDragNDrop(node, { - onStart: function() { - wasPinned = layout.isNodePinned(node); - layout.pinNode(node, true); - userInteraction = true; - resetStable(); - }, - onDrag: function(e, offset) { - var oldPos = layout.getNodePosition(node.id); - layout.setNodePosition(node.id, - oldPos.x + offset.x / transform.scale, - oldPos.y + offset.y / transform.scale); - - userInteraction = true; - - renderGraph(); - }, - onStop: function() { - layout.pinNode(node, wasPinned); - userInteraction = false; - } - }); - } - - function releaseNodeEvents(node) { - inputManager.bindDragNDrop(node, null); - } - - function initDom() { - graphics.init(container); - - graph.forEachNode(createNodeUi); - - if (settings.renderLinks) { - graph.forEachLink(createLinkUi); - } - } - - function releaseDom() { - graphics.release(container); - } - - function processNodeChange(change) { - var node = change.node; - - if (change.changeType === 'add') { - createNodeUi(node); - listenNodeEvents(node); - if (updateCenterRequired) { - updateCenter(); - } - } else if (change.changeType === 'remove') { - releaseNodeEvents(node); - removeNodeUi(node); - if (graph.getNodesCount() === 0) { - updateCenterRequired = true; // Next time when node is added - center the graph. - } - } else if (change.changeType === 'update') { - releaseNodeEvents(node); - removeNodeUi(node); - - createNodeUi(node); - listenNodeEvents(node); - } - } - - function processLinkChange(change) { - var link = change.link; - if (change.changeType === 'add') { - if (settings.renderLinks) { - createLinkUi(link); - } - } else if (change.changeType === 'remove') { - if (settings.renderLinks) { - removeLinkUi(link); - } - } else if (change.changeType === 'update') { - throw 'Update type is not implemented. TODO: Implement me!'; - } - } +/** + * @fileOverview Defines a graph renderer that uses CSS based drawings. + * + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka + */ + +module.exports = renderer; + +var eventify = require('ngraph.events'); +var forceDirected = require('ngraph.forcelayout'); +var svgGraphics = require('./svgGraphics.js'); +var windowEvents = require('../Utils/windowEvents.js'); +var domInputManager = require('../Input/domInputManager.js'); +var timer = require('../Utils/timer.js'); +var getDimension = require('../Utils/getDimensions.js'); +var dragndrop = require('../Input/dragndrop.js'); + +/** + * This is heart of the rendering. Class accepts graph to be rendered and rendering settings. + * It monitors graph changes and depicts them accordingly. + * + * @param graph - Viva.Graph.graph() object to be rendered. + * @param settings - rendering settings, composed from the following parts (with their defaults shown): + * settings = { + * // Represents a module that is capable of displaying graph nodes and links. + * // all graphics has to correspond to defined interface and can be later easily + * // replaced for specific needs (e.g. adding WebGL should be piece of cake as long + * // as WebGL has implemented required interface). See svgGraphics for example. + * graphics : Viva.Graph.View.svgGraphics(), + * + * // Where the renderer should draw graph. Container size matters, because + * // renderer will attempt center graph to that size. Also graphics modules + * // might depend on it. + * container : document.body, + * + * // Defines whether graph can respond to use input + * interactive: true, + * + * // Layout algorithm to be used. The algorithm is expected to comply with defined + * // interface and is expected to be iterative. Renderer will use it then to calculate + * // grpaph's layout. For examples of the interface refer to Viva.Graph.Layout.forceDirected() + * layout : Viva.Graph.Layout.forceDirected(), + * + * // Directs renderer to display links. Usually rendering links is the slowest part of this + * // library. So if you don't need to display links, consider settings this property to false. + * renderLinks : true, + * + * // Number of layout iterations to run before displaying the graph. The bigger you set this number + * // the closer to ideal position graph will appear first time. But be careful: for large graphs + * // it can freeze the browser. + * prerender : 0 + * } + */ +function renderer(graph, settings) { + // TODO: This class is getting hard to understand. Consider refactoring. + // TODO: I have a technical debt here: fix scaling/recentering! Currently it's a total mess. + var FRAME_INTERVAL = 30; + + settings = settings || {}; + + var layout = settings.layout, + graphics = settings.graphics, + container = settings.container, + interactive = settings.interactive !== undefined ? settings.interactive : true, + inputManager, + animationTimer, + rendererInitialized = false, + updateCenterRequired = true, + + isStable = false, + userInteraction = false, + isPaused = false, + + transform = { + offsetX: 0, + offsetY: 0, + scale: 1 + }, + + publicEvents = eventify({}), + containerDrag; + + return { + /** + * Performs rendering of the graph. + * + * @param iterationsCount if specified renderer will run only given number of iterations + * and then stop. Otherwise graph rendering is performed indefinitely. + * + * Note: if rendering stopped by used started dragging nodes or new nodes were added to the + * graph renderer will give run more iterations to reflect changes. + */ + run: function(iterationsCount) { + + if (!rendererInitialized) { + prepareSettings(); + prerender(); + + initDom(); + updateCenter(); + listenToEvents(); + + rendererInitialized = true; + } + + renderIterations(iterationsCount); + + return this; + }, + + reset: function() { + graphics.resetScale(); + updateCenter(); + transform.scale = 1; + }, + + pause: function() { + isPaused = true; + animationTimer.stop(); + }, + + resume: function() { + isPaused = false; + animationTimer.restart(); + }, + + rerender: function() { + renderGraph(); + return this; + }, + + zoomOut: function() { + return scale(true); + }, + + zoomIn: function() { + return scale(false); + }, + + /** + * Returns current transformation matrix. + */ + getTransform: function() { + return transform; + }, + + /** + * Centers renderer at x,y graph's coordinates + */ + moveTo: function(x, y) { + graphics.graphCenterChanged(transform.offsetX - x * transform.scale, transform.offsetY - y * transform.scale); + renderGraph(); + }, + + /** + * Gets current graphics object + */ + getGraphics: function() { + return graphics; + }, + + /** + * Removes this renderer and deallocates all resources/timers + */ + dispose: function() { + stopListenToEvents(); // I quit! + }, + + on: function(eventName, callback) { + publicEvents.on(eventName, callback); + return this; + }, + + off: function(eventName, callback) { + publicEvents.off(eventName, callback); + return this; + } + }; + + /** + * Checks whether given interaction (node/scroll) is enabled + */ + function isInteractive(interactionName) { + if (typeof interactive === 'string') { + return interactive.indexOf(interactionName) >= 0; + } else if (typeof interactive === 'boolean') { + return interactive; + } + return true; // default setting + } + + function prepareSettings() { + container = container || window.document.body; + layout = layout || forceDirected(graph, { + springLength: 80, + springCoeff: 0.0002, + }); + graphics = graphics || svgGraphics(graph, { + container: container + }); + + if (!settings.hasOwnProperty('renderLinks')) { + settings.renderLinks = true; + } + + settings.prerender = settings.prerender || 0; + inputManager = (graphics.inputManager || domInputManager)(graph, graphics); + } + + function renderGraph() { + graphics.beginRender(); + + // todo: move this check graphics + if (settings.renderLinks) { + graphics.renderLinks(); + } + graphics.renderNodes(); + graphics.endRender(); + } + + function onRenderFrame() { + isStable = layout.step() && !userInteraction; + renderGraph(); + + return !isStable; + } + + function renderIterations(iterationsCount) { + if (animationTimer) { + return; + } + + if (iterationsCount !== undefined) { + animationTimer = timer(function() { + iterationsCount -= 1; + if (iterationsCount < 0) { + var needMoreFrames = false; + return needMoreFrames; + } + + return onRenderFrame(); + }, FRAME_INTERVAL); + } else { + animationTimer = timer(onRenderFrame, FRAME_INTERVAL); + } + } + + function resetStable() { + if (isPaused) { + return; + } + + isStable = false; + animationTimer.restart(); + } + + function prerender() { + // To get good initial positions for the graph + // perform several prerender steps in background. + if (typeof settings.prerender === 'number' && settings.prerender > 0) { + for (var i = 0; i < settings.prerender; i += 1) { + layout.step(); + } + } + } + + function updateCenter() { + var graphRect = layout.getGraphRect(), + containerSize = getDimension(container); + + var cx = (graphRect.x2 + graphRect.x1) / 2; + var cy = (graphRect.y2 + graphRect.y1) / 2; + transform.offsetX = containerSize.width / 2 - (cx * transform.scale - cx); + transform.offsetY = containerSize.height / 2 - (cy * transform.scale - cy); + graphics.graphCenterChanged(transform.offsetX, transform.offsetY); + + updateCenterRequired = false; + } + + function createNodeUi(node) { + var nodePosition = layout.getNodePosition(node.id); + graphics.addNode(node, nodePosition); + } + + function removeNodeUi(node) { + graphics.releaseNode(node); + } + + function createLinkUi(link) { + var linkPosition = layout.getLinkPosition(link.id); + graphics.addLink(link, linkPosition); + } + + function removeLinkUi(link) { + graphics.releaseLink(link); + } + + function listenNodeEvents(node) { + if (!isInteractive('node')) { + return; + } + + var wasPinned = false; + + // TODO: This may not be memory efficient. Consider reusing handlers object. + inputManager.bindDragNDrop(node, { + onStart: function() { + wasPinned = layout.isNodePinned(node); + layout.pinNode(node, true); + userInteraction = true; + resetStable(); + }, + onDrag: function(e, offset) { + var oldPos = layout.getNodePosition(node.id); + layout.setNodePosition(node.id, + oldPos.x + offset.x / transform.scale, + oldPos.y + offset.y / transform.scale); + + userInteraction = true; + + renderGraph(); + }, + onStop: function() { + layout.pinNode(node, wasPinned); + userInteraction = false; + } + }); + } + + function releaseNodeEvents(node) { + inputManager.bindDragNDrop(node, null); + } + + function initDom() { + graphics.init(container); + + graph.forEachNode(createNodeUi); + + if (settings.renderLinks) { + graph.forEachLink(createLinkUi); + } + } + + function releaseDom() { + graphics.release(container); + } + + function processNodeChange(change) { + var node = change.node; + + if (change.changeType === 'add') { + createNodeUi(node); + listenNodeEvents(node); + if (updateCenterRequired) { + updateCenter(); + } + } else if (change.changeType === 'remove') { + releaseNodeEvents(node); + removeNodeUi(node); + if (graph.getNodesCount() === 0) { + updateCenterRequired = true; // Next time when node is added - center the graph. + } + } else if (change.changeType === 'update') { + releaseNodeEvents(node); + removeNodeUi(node); + + createNodeUi(node); + listenNodeEvents(node); + } + } + + function processLinkChange(change) { + var link = change.link; + if (change.changeType === 'add') { + if (settings.renderLinks) { + createLinkUi(link); + } + } else if (change.changeType === 'remove') { + if (settings.renderLinks) { + removeLinkUi(link); + } + } else if (change.changeType === 'update') { + throw 'Update type is not implemented. TODO: Implement me!'; + } + } + + function onGraphChanged(changes) { + var i, change; + for (i = 0; i < changes.length; i += 1) { + change = changes[i]; + if (change.node) { + processNodeChange(change); + } else if (change.link) { + processLinkChange(change); + } + } + + resetStable(); + } + + function onWindowResized() { + updateCenter(); + onRenderFrame(); + } + + function releaseContainerDragManager() { + if (containerDrag) { + containerDrag.release(); + containerDrag = null; + } + } + + function releaseGraphEvents() { + graph.off('changed', onGraphChanged); + } + + function scale(out, scrollPoint) { + if (!scrollPoint) { + var containerSize = getDimension(container); + scrollPoint = { + x: containerSize.width / 2, + y: containerSize.height / 2 + }; + } + var scaleFactor = Math.pow(1 + 0.4, out ? -0.2 : 0.2); + transform.scale = graphics.scale(scaleFactor, scrollPoint); + + renderGraph(); + publicEvents.fire('scale', transform.scale); + + return transform.scale; + } + + function listenToEvents() { + windowEvents.on('resize', onWindowResized); + + releaseContainerDragManager(); + if (isInteractive('drag')) { + containerDrag = dragndrop(container); + containerDrag.onDrag(function(e, offset) { + graphics.translateRel(offset.x, offset.y); + + renderGraph(); + publicEvents.fire('drag', offset); + }); + } + + if (isInteractive('scroll')) { + if (!containerDrag) { + containerDrag = dragndrop(container); + } + containerDrag.onScroll(function(e, scaleOffset, scrollPoint) { + scale(scaleOffset < 0, scrollPoint); + }); + } + + graph.forEachNode(listenNodeEvents); + + releaseGraphEvents(); + graph.on('changed', onGraphChanged); + } + + function stopListenToEvents() { + rendererInitialized = false; + releaseGraphEvents(); + releaseContainerDragManager(); + windowEvents.off('resize', onWindowResized); + publicEvents.off(); + animationTimer.stop(); + + graph.forEachLink(function(link) { + if (settings.renderLinks) { + removeLinkUi(link); + } + }); + + graph.forEachNode(function(node) { + releaseNodeEvents(node); + removeNodeUi(node); + }); + + layout.dispose(); + releaseDom(); + } +} - function onGraphChanged(changes) { - var i, change; - for (i = 0; i < changes.length; i += 1) { - change = changes[i]; - if (change.node) { - processNodeChange(change); - } else if (change.link) { - processLinkChange(change); - } - } - - resetStable(); - } - - function onWindowResized() { - updateCenter(); - onRenderFrame(); - } - - function releaseContainerDragManager() { - if (containerDrag) { - containerDrag.release(); - containerDrag = null; - } - } - - function releaseGraphEvents() { - graph.off('changed', onGraphChanged); - } - - function scale(out, scrollPoint) { - if (!scrollPoint) { - var containerSize = getDimension(container); - scrollPoint = { - x: containerSize.width / 2, - y: containerSize.height / 2 - }; - } - var scaleFactor = Math.pow(1 + 0.4, out ? -0.2 : 0.2); - transform.scale = graphics.scale(scaleFactor, scrollPoint); - - renderGraph(); - publicEvents.fire('scale', transform.scale); - - return transform.scale; - } - - function listenToEvents() { - windowEvents.on('resize', onWindowResized); - - releaseContainerDragManager(); - if (isInteractive('drag')) { - containerDrag = dragndrop(container); - containerDrag.onDrag(function(e, offset) { - graphics.translateRel(offset.x, offset.y); - - renderGraph(); - publicEvents.fire('drag', offset); - }); - } - - if (isInteractive('scroll')) { - if (!containerDrag) { - containerDrag = dragndrop(container); - } - containerDrag.onScroll(function(e, scaleOffset, scrollPoint) { - scale(scaleOffset < 0, scrollPoint); - }); - } - - graph.forEachNode(listenNodeEvents); - - releaseGraphEvents(); - graph.on('changed', onGraphChanged); - } - - function stopListenToEvents() { - rendererInitialized = false; - releaseGraphEvents(); - releaseContainerDragManager(); - windowEvents.off('resize', onWindowResized); - publicEvents.off(); - animationTimer.stop(); - - graph.forEachLink(function(link) { - if (settings.renderLinks) { - removeLinkUi(link); - } - }); - - graph.forEachNode(function(node) { - releaseNodeEvents(node); - removeNodeUi(node); - }); - - layout.dispose(); - releaseDom(); - } -} - -},{"../Input/domInputManager.js":34,"../Input/dragndrop.js":35,"../Utils/getDimensions.js":42,"../Utils/timer.js":46,"../Utils/windowEvents.js":47,"./svgGraphics.js":49,"ngraph.events":7,"ngraph.forcelayout":9}],49:[function(require,module,exports){ -/** - * @fileOverview Defines a graph renderer that uses SVG based drawings. - * - * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka - */ - -module.exports = svgGraphics; - -var svg = require('simplesvg'); -var eventify = require('ngraph.events'); -var domInputManager = require('../Input/domInputManager.js'); - -/** - * Performs svg-based graph rendering. This module does not perform - * layout, but only visualizes nodes and edges of the graph. - */ -function svgGraphics() { - var svgContainer, - svgRoot, - offsetX = 0, - offsetY = 0, - initCallback, - actualScale = 1, - allNodes = {}, - allLinks = {}, -/*jshint unused: false */ - nodeBuilder = function (node) { - return svg("rect") - .attr("width", 10) - .attr("height", 10) - .attr("fill", "#00a2e8"); - }, - - nodePositionCallback = function (nodeUI, pos) { - // TODO: Remove magic 5. It should be half of the width or height of the node. - nodeUI.attr("x", pos.x - 5) - .attr("y", pos.y - 5); - }, - - linkBuilder = function (link) { - return svg("line").attr("stroke", "#999"); - }, - - linkPositionCallback = function (linkUI, fromPos, toPos) { - linkUI.attr("x1", fromPos.x) - .attr("y1", fromPos.y) - .attr("x2", toPos.x) - .attr("y2", toPos.y); - }, - - fireRescaled = function (graphics) { - // TODO: maybe we shall copy changes? - graphics.fire("rescaled"); - }, - - cachedPos = {x : 0, y: 0}, - cachedFromPos = {x : 0, y: 0}, - cachedToPos = {x : 0, y: 0}, - - updateTransform = function () { - if (svgContainer) { - var transform = "matrix(" + actualScale + ", 0, 0," + actualScale + "," + offsetX + "," + offsetY + ")"; - svgContainer.attr("transform", transform); - } - }; - - svgRoot = createSvgRoot(); - - var graphics = { - getNodeUI: function (nodeId) { - return allNodes[nodeId]; - }, - - getLinkUI: function (linkId) { - return allLinks[linkId]; - }, - - /** - * Sets the callback that creates node representation. - * - * @param builderCallback a callback function that accepts graph node - * as a parameter and must return an element representing this node. - * - * @returns If builderCallbackOrNode is a valid callback function, instance of this is returned; - * Otherwise undefined value is returned - */ - node : function (builderCallback) { - if (typeof builderCallback !== "function") { - return; // todo: throw? This is not compatible with old versions - } - - nodeBuilder = builderCallback; - - return this; - }, - - /** - * Sets the callback that creates link representation - * - * @param builderCallback a callback function that accepts graph link - * as a parameter and must return an element representing this link. - * - * @returns If builderCallback is a valid callback function, instance of this is returned; - * Otherwise undefined value is returned. - */ - link : function (builderCallback) { - if (typeof builderCallback !== "function") { - return; // todo: throw? This is not compatible with old versions - } - - linkBuilder = builderCallback; - return this; - }, - - /** - * Allows to override default position setter for the node with a new - * function. newPlaceCallback(nodeUI, position, node) is function which - * is used by updateNodePosition(). - */ - placeNode : function (newPlaceCallback) { - nodePositionCallback = newPlaceCallback; - return this; - }, - - placeLink : function (newPlaceLinkCallback) { - linkPositionCallback = newPlaceLinkCallback; - return this; - }, - - /** - * Called every before renderer starts rendering. - */ - beginRender : function () {}, - - /** - * Called every time when renderer finishes one step of rendering. - */ - endRender : function () {}, - - /** - * Sets translate operation that should be applied to all nodes and links. - */ - graphCenterChanged : function (x, y) { - offsetX = x; - offsetY = y; - updateTransform(); - }, - - /** - * Default input manager listens to DOM events to process nodes drag-n-drop - */ - inputManager : domInputManager, - - translateRel : function (dx, dy) { - var p = svgRoot.createSVGPoint(), - t = svgContainer.getCTM(), - origin = svgRoot.createSVGPoint().matrixTransform(t.inverse()); - - p.x = dx; - p.y = dy; - - p = p.matrixTransform(t.inverse()); - p.x = (p.x - origin.x) * t.a; - p.y = (p.y - origin.y) * t.d; - - t.e += p.x; - t.f += p.y; - - var transform = "matrix(" + t.a + ", 0, 0," + t.d + "," + t.e + "," + t.f + ")"; - svgContainer.attr("transform", transform); - }, - - scale : function (scaleFactor, scrollPoint) { - var p = svgRoot.createSVGPoint(); - p.x = scrollPoint.x; - p.y = scrollPoint.y; - - p = p.matrixTransform(svgContainer.getCTM().inverse()); // translate to SVG coordinates - - // Compute new scale matrix in current mouse position - var k = svgRoot.createSVGMatrix().translate(p.x, p.y).scale(scaleFactor).translate(-p.x, -p.y), - t = svgContainer.getCTM().multiply(k); - - actualScale = t.a; - offsetX = t.e; - offsetY = t.f; - var transform = "matrix(" + t.a + ", 0, 0," + t.d + "," + t.e + "," + t.f + ")"; - svgContainer.attr("transform", transform); - - fireRescaled(this); - return actualScale; - }, - - resetScale : function () { - actualScale = 1; - var transform = "matrix(1, 0, 0, 1, 0, 0)"; - svgContainer.attr("transform", transform); - fireRescaled(this); - return this; - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render. - */ - init : function (container) { - container.appendChild(svgRoot); - updateTransform(); - // Notify the world if someone waited for update. TODO: should send an event - if (typeof initCallback === "function") { - initCallback(svgRoot); - } - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider release occupied resources. - */ - release : function (container) { - if (svgRoot && container) { - container.removeChild(svgRoot); - } - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render given link of the graph - * - * @param link - model of a link - */ - addLink: function (link, pos) { - var linkUI = linkBuilder(link); - if (!linkUI) { return; } - linkUI.position = pos; - linkUI.link = link; - allLinks[link.id] = linkUI; - if (svgContainer.childElementCount > 0) { - svgContainer.insertBefore(linkUI, svgContainer.firstChild); - } else { - svgContainer.appendChild(linkUI); - } - return linkUI; - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider remove link from rendering surface. - * - * @param linkUI visual representation of the link created by link() execution. - **/ - releaseLink : function (link) { - var linkUI = allLinks[link.id]; - if (linkUI) { - svgContainer.removeChild(linkUI); - delete allLinks[link.id]; - } - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render given node of the graph. - * - * @param nodeUI visual representation of the node created by node() execution. - **/ - addNode : function (node, pos) { - var nodeUI = nodeBuilder(node); - if (!nodeUI) { - return; - } - nodeUI.position = pos; - nodeUI.node = node; - allNodes[node.id] = nodeUI; - - svgContainer.appendChild(nodeUI); - - return nodeUI; - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider remove node from rendering surface. - * - * @param node graph's node - **/ - releaseNode : function (node) { - var nodeUI = allNodes[node.id]; - if (nodeUI) { - svgContainer.removeChild(nodeUI); - delete allNodes[node.id]; - } - }, - - renderNodes : function () { - for (var key in allNodes) { - if (allNodes.hasOwnProperty(key)) { - var nodeUI = allNodes[key]; - cachedPos.x = nodeUI.position.x; - cachedPos.y = nodeUI.position.y; - nodePositionCallback(nodeUI, cachedPos, nodeUI.node); - } - } - }, - - renderLinks : function () { - for (var key in allLinks) { - if (allLinks.hasOwnProperty(key)) { - var linkUI = allLinks[key]; - cachedFromPos.x = linkUI.position.from.x; - cachedFromPos.y = linkUI.position.from.y; - cachedToPos.x = linkUI.position.to.x; - cachedToPos.y = linkUI.position.to.y; - linkPositionCallback(linkUI, cachedFromPos, cachedToPos, linkUI.link); - } - } - }, - - /** - * Returns root element which hosts graphics. - */ - getGraphicsRoot : function (callbackWhenReady) { - // todo: should fire an event, instead of having this context. - if (typeof callbackWhenReady === "function") { - if (svgRoot) { - callbackWhenReady(svgRoot); - } else { - initCallback = callbackWhenReady; - } - } - return svgRoot; - }, - /** - * Returns root SVG element. - * - * Note: This is internal method specific to this renderer - */ - getSvgRoot : function () { - return svgRoot; - } - }; - - - // Let graphics fire events before we return it to the caller. - eventify(graphics); - - return graphics; - - function createSvgRoot() { - var svgRoot = svg("svg"); - - svgContainer = svg("g") - .attr("buffered-rendering", "dynamic"); - - svgRoot.appendChild(svgContainer); - return svgRoot; - } -} +},{"../Input/domInputManager.js":34,"../Input/dragndrop.js":35,"../Utils/getDimensions.js":42,"../Utils/timer.js":46,"../Utils/windowEvents.js":47,"./svgGraphics.js":49,"ngraph.events":7,"ngraph.forcelayout":9}],49:[function(require,module,exports){ +/** + * @fileOverview Defines a graph renderer that uses SVG based drawings. + * + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka + */ + +module.exports = svgGraphics; + +var svg = require('simplesvg'); +var eventify = require('ngraph.events'); +var domInputManager = require('../Input/domInputManager.js'); + +/** + * Performs svg-based graph rendering. This module does not perform + * layout, but only visualizes nodes and edges of the graph. + */ +function svgGraphics() { + var svgContainer, + svgRoot, + offsetX = 0, + offsetY = 0, + initCallback, + actualScale = 1, + allNodes = {}, + allLinks = {}, +/*jshint unused: false */ + nodeBuilder = function (node) { + return svg("rect") + .attr("width", 10) + .attr("height", 10) + .attr("fill", "#00a2e8"); + }, + + nodePositionCallback = function (nodeUI, pos) { + // TODO: Remove magic 5. It should be half of the width or height of the node. + nodeUI.attr("x", pos.x - 5) + .attr("y", pos.y - 5); + }, + + linkBuilder = function (link) { + return svg("line").attr("stroke", "#999"); + }, + + linkPositionCallback = function (linkUI, fromPos, toPos) { + linkUI.attr("x1", fromPos.x) + .attr("y1", fromPos.y) + .attr("x2", toPos.x) + .attr("y2", toPos.y); + }, + + fireRescaled = function (graphics) { + // TODO: maybe we shall copy changes? + graphics.fire("rescaled"); + }, + + cachedPos = {x : 0, y: 0}, + cachedFromPos = {x : 0, y: 0}, + cachedToPos = {x : 0, y: 0}, + + updateTransform = function () { + if (svgContainer) { + var transform = "matrix(" + actualScale + ", 0, 0," + actualScale + "," + offsetX + "," + offsetY + ")"; + svgContainer.attr("transform", transform); + } + }; + + svgRoot = createSvgRoot(); + + var graphics = { + getNodeUI: function (nodeId) { + return allNodes[nodeId]; + }, + + getLinkUI: function (linkId) { + return allLinks[linkId]; + }, + + /** + * Sets the callback that creates node representation. + * + * @param builderCallback a callback function that accepts graph node + * as a parameter and must return an element representing this node. + * + * @returns If builderCallbackOrNode is a valid callback function, instance of this is returned; + * Otherwise undefined value is returned + */ + node : function (builderCallback) { + if (typeof builderCallback !== "function") { + return; // todo: throw? This is not compatible with old versions + } + + nodeBuilder = builderCallback; + + return this; + }, + + /** + * Sets the callback that creates link representation + * + * @param builderCallback a callback function that accepts graph link + * as a parameter and must return an element representing this link. + * + * @returns If builderCallback is a valid callback function, instance of this is returned; + * Otherwise undefined value is returned. + */ + link : function (builderCallback) { + if (typeof builderCallback !== "function") { + return; // todo: throw? This is not compatible with old versions + } + + linkBuilder = builderCallback; + return this; + }, + + /** + * Allows to override default position setter for the node with a new + * function. newPlaceCallback(nodeUI, position, node) is function which + * is used by updateNodePosition(). + */ + placeNode : function (newPlaceCallback) { + nodePositionCallback = newPlaceCallback; + return this; + }, + + placeLink : function (newPlaceLinkCallback) { + linkPositionCallback = newPlaceLinkCallback; + return this; + }, + + /** + * Called every before renderer starts rendering. + */ + beginRender : function () {}, + + /** + * Called every time when renderer finishes one step of rendering. + */ + endRender : function () {}, + + /** + * Sets translate operation that should be applied to all nodes and links. + */ + graphCenterChanged : function (x, y) { + offsetX = x; + offsetY = y; + updateTransform(); + }, + + /** + * Default input manager listens to DOM events to process nodes drag-n-drop + */ + inputManager : domInputManager, + + translateRel : function (dx, dy) { + var p = svgRoot.createSVGPoint(), + t = svgContainer.getCTM(), + origin = svgRoot.createSVGPoint().matrixTransform(t.inverse()); + + p.x = dx; + p.y = dy; + + p = p.matrixTransform(t.inverse()); + p.x = (p.x - origin.x) * t.a; + p.y = (p.y - origin.y) * t.d; + + t.e += p.x; + t.f += p.y; + + var transform = "matrix(" + t.a + ", 0, 0," + t.d + "," + t.e + "," + t.f + ")"; + svgContainer.attr("transform", transform); + }, + + scale : function (scaleFactor, scrollPoint) { + var p = svgRoot.createSVGPoint(); + p.x = scrollPoint.x; + p.y = scrollPoint.y; + + p = p.matrixTransform(svgContainer.getCTM().inverse()); // translate to SVG coordinates + + // Compute new scale matrix in current mouse position + var k = svgRoot.createSVGMatrix().translate(p.x, p.y).scale(scaleFactor).translate(-p.x, -p.y), + t = svgContainer.getCTM().multiply(k); + + actualScale = t.a; + offsetX = t.e; + offsetY = t.f; + var transform = "matrix(" + t.a + ", 0, 0," + t.d + "," + t.e + "," + t.f + ")"; + svgContainer.attr("transform", transform); + + fireRescaled(this); + return actualScale; + }, + + resetScale : function () { + actualScale = 1; + var transform = "matrix(1, 0, 0, 1, 0, 0)"; + svgContainer.attr("transform", transform); + fireRescaled(this); + return this; + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render. + */ + init : function (container) { + container.appendChild(svgRoot); + updateTransform(); + // Notify the world if someone waited for update. TODO: should send an event + if (typeof initCallback === "function") { + initCallback(svgRoot); + } + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider release occupied resources. + */ + release : function (container) { + if (svgRoot && container) { + container.removeChild(svgRoot); + } + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render given link of the graph + * + * @param link - model of a link + */ + addLink: function (link, pos) { + var linkUI = linkBuilder(link); + if (!linkUI) { return; } + linkUI.position = pos; + linkUI.link = link; + allLinks[link.id] = linkUI; + if (svgContainer.childElementCount > 0) { + svgContainer.insertBefore(linkUI, svgContainer.firstChild); + } else { + svgContainer.appendChild(linkUI); + } + return linkUI; + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider remove link from rendering surface. + * + * @param linkUI visual representation of the link created by link() execution. + **/ + releaseLink : function (link) { + var linkUI = allLinks[link.id]; + if (linkUI) { + svgContainer.removeChild(linkUI); + delete allLinks[link.id]; + } + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render given node of the graph. + * + * @param nodeUI visual representation of the node created by node() execution. + **/ + addNode : function (node, pos) { + var nodeUI = nodeBuilder(node); + if (!nodeUI) { + return; + } + nodeUI.position = pos; + nodeUI.node = node; + allNodes[node.id] = nodeUI; + + svgContainer.appendChild(nodeUI); + + return nodeUI; + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider remove node from rendering surface. + * + * @param node graph's node + **/ + releaseNode : function (node) { + var nodeUI = allNodes[node.id]; + if (nodeUI) { + svgContainer.removeChild(nodeUI); + delete allNodes[node.id]; + } + }, + + renderNodes : function () { + for (var key in allNodes) { + if (allNodes.hasOwnProperty(key)) { + var nodeUI = allNodes[key]; + cachedPos.x = nodeUI.position.x; + cachedPos.y = nodeUI.position.y; + nodePositionCallback(nodeUI, cachedPos, nodeUI.node); + } + } + }, + + renderLinks : function () { + for (var key in allLinks) { + if (allLinks.hasOwnProperty(key)) { + var linkUI = allLinks[key]; + cachedFromPos.x = linkUI.position.from.x; + cachedFromPos.y = linkUI.position.from.y; + cachedToPos.x = linkUI.position.to.x; + cachedToPos.y = linkUI.position.to.y; + linkPositionCallback(linkUI, cachedFromPos, cachedToPos, linkUI.link); + } + } + }, + + /** + * Returns root element which hosts graphics. + */ + getGraphicsRoot : function (callbackWhenReady) { + // todo: should fire an event, instead of having this context. + if (typeof callbackWhenReady === "function") { + if (svgRoot) { + callbackWhenReady(svgRoot); + } else { + initCallback = callbackWhenReady; + } + } + return svgRoot; + }, + /** + * Returns root SVG element. + * + * Note: This is internal method specific to this renderer + */ + getSvgRoot : function () { + return svgRoot; + } + }; + + + // Let graphics fire events before we return it to the caller. + eventify(graphics); + + return graphics; + + function createSvgRoot() { + var svgRoot = svg("svg"); + + svgContainer = svg("g") + .attr("buffered-rendering", "dynamic"); + + svgRoot.appendChild(svgContainer); + return svgRoot; + } +} },{"../Input/domInputManager.js":34,"ngraph.events":7,"simplesvg":28}],50:[function(require,module,exports){ -/** - * @fileOverview Defines a graph renderer that uses WebGL based drawings. - * - * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka - */ - -module.exports = webglGraphics; - -var webglInputManager = require('../Input/webglInputManager.js'); -var webglLinkProgram = require('../WebGL/webglLinkProgram.js'); -var webglNodeProgram = require('../WebGL/webglNodeProgram.js'); -var webglSquare = require('../WebGL/webglSquare.js'); -var webglLine = require('../WebGL/webglLine.js'); -var eventify = require('ngraph.events'); -var merge = require('ngraph.merge'); - -/** - * Performs webgl-based graph rendering. This module does not perform - * layout, but only visualizes nodes and edges of the graph. - * - * @param options - to customize graphics behavior. Currently supported parameter - * enableBlending - true by default, allows to use transparency in node/links colors. - * preserveDrawingBuffer - false by default, tells webgl to preserve drawing buffer. - * See https://www.khronos.org/registry/webgl/specs/1.0/#5.2 - */ - -function webglGraphics(options) { - options = merge(options, { - enableBlending : true, - preserveDrawingBuffer : false, - clearColor: false, - clearColorValue : { - r : 1, - g : 1, - b : 1, - a : 1 - } - }); - - var container, - graphicsRoot, - gl, - width, - height, - nodesCount = 0, - linksCount = 0, - transform = [ - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - ], - userPlaceNodeCallback, - userPlaceLinkCallback, - nodes = [], - links = [], - initCallback, - - allNodes = {}, - allLinks = {}, - linkProgram = webglLinkProgram(), - nodeProgram = webglNodeProgram(), -/*jshint unused: false */ - nodeUIBuilder = function (node) { - return webglSquare(); // Just make a square, using provided gl context (a nodeProgram); - }, - - linkUIBuilder = function (link) { - return webglLine(0xb3b3b3ff); - }, -/*jshint unused: true */ - updateTransformUniform = function () { - linkProgram.updateTransform(transform); - nodeProgram.updateTransform(transform); - }, - - resetScaleInternal = function () { - transform = [1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1]; - }, - - updateSize = function () { - if (container && graphicsRoot) { - width = graphicsRoot.width = Math.max(container.offsetWidth, 1); - height = graphicsRoot.height = Math.max(container.offsetHeight, 1); - if (gl) { gl.viewport(0, 0, width, height); } - if (linkProgram) { linkProgram.updateSize(width / 2, height / 2); } - if (nodeProgram) { nodeProgram.updateSize(width / 2, height / 2); } - } - }, - - fireRescaled = function (graphics) { - graphics.fire("rescaled"); - }; - - graphicsRoot = window.document.createElement("canvas"); - - var graphics = { - getLinkUI: function (linkId) { - return allLinks[linkId]; - }, - - getNodeUI: function (nodeId) { - return allNodes[nodeId]; - }, - - /** - * Sets the callback that creates node representation. - * - * @param builderCallback a callback function that accepts graph node - * as a parameter and must return an element representing this node. - * - * @returns If builderCallbackOrNode is a valid callback function, instance of this is returned; - * Otherwise undefined value is returned - */ - node : function (builderCallback) { - if (typeof builderCallback !== "function") { - return; // todo: throw? This is not compatible with old versions - } - - nodeUIBuilder = builderCallback; - - return this; - }, - - /** - * Sets the callback that creates link representation - * - * @param builderCallback a callback function that accepts graph link - * as a parameter and must return an element representing this link. - * - * @returns If builderCallback is a valid callback function, instance of this is returned; - * Otherwise undefined value is returned. - */ - link : function (builderCallback) { - if (typeof builderCallback !== "function") { - return; // todo: throw? This is not compatible with old versions - } - - linkUIBuilder = builderCallback; - return this; - }, - - - /** - * Allows to override default position setter for the node with a new - * function. newPlaceCallback(nodeUI, position) is function which - * is used by updateNodePosition(). - */ - placeNode : function (newPlaceCallback) { - userPlaceNodeCallback = newPlaceCallback; - return this; - }, - - placeLink : function (newPlaceLinkCallback) { - userPlaceLinkCallback = newPlaceLinkCallback; - return this; - }, - - /** - * Custom input manager listens to mouse events to process nodes drag-n-drop inside WebGL canvas - */ - inputManager : webglInputManager, - - /** - * Called every time before renderer starts rendering. - */ - beginRender : function () { - // this function could be replaced by this.init, - // based on user options. - }, - - /** - * Called every time when renderer finishes one step of rendering. - */ - endRender : function () { - if (linksCount > 0) { - linkProgram.render(); - } - if (nodesCount > 0) { - nodeProgram.render(); - } - }, - - bringLinkToFront : function (linkUI) { - var frontLinkId = linkProgram.getFrontLinkId(), - srcLinkId, - temp; - - linkProgram.bringToFront(linkUI); - - if (frontLinkId > linkUI.id) { - srcLinkId = linkUI.id; - - temp = links[frontLinkId]; - links[frontLinkId] = links[srcLinkId]; - links[frontLinkId].id = frontLinkId; - links[srcLinkId] = temp; - links[srcLinkId].id = srcLinkId; - } - }, - - /** - * Sets translate operation that should be applied to all nodes and links. - */ - graphCenterChanged : function (x, y) { - transform[12] = (2 * x / width) - 1; - transform[13] = 1 - (2 * y / height); - updateTransformUniform(); - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render given link of the graph - * - * @param link - model of a link - */ - addLink: function (link, boundPosition) { - var uiid = linksCount++, - ui = linkUIBuilder(link); - ui.id = uiid; - ui.pos = boundPosition; - - linkProgram.createLink(ui); - - links[uiid] = ui; - allLinks[link.id] = ui; - return ui; - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render given node of the graph. - * - * @param nodeUI visual representation of the node created by node() execution. - **/ - addNode : function (node, boundPosition) { - var uiid = nodesCount++, - ui = nodeUIBuilder(node); - - ui.id = uiid; - ui.position = boundPosition; - ui.node = node; - - nodeProgram.createNode(ui); - - nodes[uiid] = ui; - allNodes[node.id] = ui; - return ui; - }, - - translateRel : function (dx, dy) { - transform[12] += (2 * transform[0] * dx / width) / transform[0]; - transform[13] -= (2 * transform[5] * dy / height) / transform[5]; - updateTransformUniform(); - }, - - scale : function (scaleFactor, scrollPoint) { - // Transform scroll point to clip-space coordinates: - var cx = 2 * scrollPoint.x / width - 1, - cy = 1 - (2 * scrollPoint.y) / height; - - cx -= transform[12]; - cy -= transform[13]; - - transform[12] += cx * (1 - scaleFactor); - transform[13] += cy * (1 - scaleFactor); - - transform[0] *= scaleFactor; - transform[5] *= scaleFactor; - - updateTransformUniform(); - fireRescaled(this); - - return transform[0]; - }, - - resetScale : function () { - resetScaleInternal(); - - if (gl) { - updateSize(); - // TODO: what is this? - // gl.useProgram(linksProgram); - // gl.uniform2f(linksProgram.screenSize, width, height); - updateTransformUniform(); - } - return this; - }, - - /** - * Resizes the graphic without resetting the scale. - * Useful with viva graph in a dynamic container - */ - updateSize: updateSize, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider prepare to render. - */ - init : function (c) { - var contextParameters = {}; - - if (options.preserveDrawingBuffer) { - contextParameters.preserveDrawingBuffer = true; - } - - container = c; - - updateSize(); - resetScaleInternal(); - container.appendChild(graphicsRoot); - - - gl = graphicsRoot.getContext("experimental-webgl", contextParameters); - if (!gl) { - var msg = "Could not initialize WebGL. Seems like the browser doesn't support it."; - window.alert(msg); - throw msg; - } - if (options.enableBlending) { - gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); - gl.enable(gl.BLEND); - } - if (options.clearColor) { - var color = options.clearColorValue; - gl.clearColor(color.r, color.g, color.b, color.a); - // TODO: not the best way, really. Should come up with something better - // what if we need more updates inside beginRender, like depth buffer? - this.beginRender = function () { - gl.clear(gl.COLOR_BUFFER_BIT); - }; - } - - linkProgram.load(gl); - linkProgram.updateSize(width / 2, height / 2); - - nodeProgram.load(gl); - nodeProgram.updateSize(width / 2, height / 2); - - updateTransformUniform(); - - // Notify the world if someone waited for update. TODO: should send an event - if (typeof initCallback === "function") { - initCallback(graphicsRoot); - } - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider release occupied resources. - */ - release : function (container) { - if (graphicsRoot && container) { - container.removeChild(graphicsRoot); - // TODO: anything else? - } - }, - - /** - * Checks whether webgl is supported by this browser. - */ - isSupported : function () { - var c = window.document.createElement("canvas"), - gl = c && c.getContext && c.getContext("experimental-webgl"); - return gl; - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider remove link from rendering surface. - * - * @param linkUI visual representation of the link created by link() execution. - **/ - releaseLink : function (link) { - if (linksCount > 0) { linksCount -= 1; } - var linkUI = allLinks[link.id]; - delete allLinks[link.id]; - - linkProgram.removeLink(linkUI); - - var linkIdToRemove = linkUI.id; - if (linkIdToRemove < linksCount) { - if (linksCount === 0 || linksCount === linkIdToRemove) { - return; // no more links or removed link is the last one. - } - - var lastLinkUI = links[linksCount]; - links[linkIdToRemove] = lastLinkUI; - lastLinkUI.id = linkIdToRemove; - } - }, - - /** - * Called by Viva.Graph.View.renderer to let concrete graphic output - * provider remove node from rendering surface. - * - * @param nodeUI visual representation of the node created by node() execution. - **/ - releaseNode : function (node) { - if (nodesCount > 0) { nodesCount -= 1; } - var nodeUI = allNodes[node.id]; - delete allNodes[node.id]; - - nodeProgram.removeNode(nodeUI); - - var nodeIdToRemove = nodeUI.id; - if (nodeIdToRemove < nodesCount) { - if (nodesCount === 0 || nodesCount === nodeIdToRemove) { - return; // no more nodes or removed node is the last in the list. - } - - var lastNodeUI = nodes[nodesCount]; - - nodes[nodeIdToRemove] = lastNodeUI; - lastNodeUI.id = nodeIdToRemove; - - // Since concrete shaders may cache properties in the UI element - // we are letting them to make this swap (e.g. image node shader - // uses this approach to update node's offset in the atlas) - nodeProgram.replaceProperties(nodeUI, lastNodeUI); - } - }, - - renderNodes: function () { - var pos = {x : 0, y : 0}; - // WebGL coordinate system is different. Would be better - // to have this transform in the shader code, but it would - // require every shader to be updated.. - for (var i = 0; i < nodesCount; ++i) { - var ui = nodes[i]; - pos.x = ui.position.x; - pos.y = ui.position.y; - if (userPlaceNodeCallback) { - userPlaceNodeCallback(ui, pos); - } - - nodeProgram.position(ui, pos); - } - }, - - renderLinks: function () { - if (this.omitLinksRendering) { return; } - - var toPos = {x : 0, y : 0}; - var fromPos = {x : 0, y : 0}; - for (var i = 0; i < linksCount; ++i) { - var ui = links[i]; - var pos = ui.pos.from; - fromPos.x = pos.x; - fromPos.y = -pos.y; - pos = ui.pos.to; - toPos.x = pos.x; - toPos.y = -pos.y; - if (userPlaceLinkCallback) { - userPlaceLinkCallback(ui, fromPos, toPos); - } - - linkProgram.position(ui, fromPos, toPos); - } - }, - - /** - * Returns root element which hosts graphics. - */ - getGraphicsRoot : function (callbackWhenReady) { - // todo: should fire an event, instead of having this context. - if (typeof callbackWhenReady === "function") { - if (graphicsRoot) { - callbackWhenReady(graphicsRoot); - } else { - initCallback = callbackWhenReady; - } - } - return graphicsRoot; - }, - - /** - * Updates default shader which renders nodes - * - * @param newProgram to use for nodes. - */ - setNodeProgram : function (newProgram) { - if (!gl && newProgram) { - // Nothing created yet. Just set shader to the new one - // and let initialization logic take care about the rest. - nodeProgram = newProgram; - } else if (newProgram) { - throw "Not implemented. Cannot swap shader on the fly... Yet."; - // TODO: unload old shader and reinit. - } - }, - - /** - * Updates default shader which renders links - * - * @param newProgram to use for links. - */ - setLinkProgram : function (newProgram) { - if (!gl && newProgram) { - // Nothing created yet. Just set shader to the new one - // and let initialization logic take care about the rest. - linkProgram = newProgram; - } else if (newProgram) { - throw "Not implemented. Cannot swap shader on the fly... Yet."; - // TODO: unload old shader and reinit. - } - }, - - /** - * Transforms client coordinates into layout coordinates. Client coordinates - * are DOM coordinates relative to the rendering container. Layout - * coordinates are those assigned by by layout algorithm to each node. - * - * @param {Object} p - a point object with `x` and `y` attributes. - * This method mutates p. - */ - transformClientToGraphCoordinates: function (p) { - // TODO: could be a problem when container has margins? - // normalize - p.x = ((2 * p.x) / width) - 1; - p.y = 1 - ((2 * p.y) / height); - - // apply transform - p.x = (p.x - transform[12]) / transform[0]; - p.y = (p.y - transform[13]) / transform[5]; - - // transform to graph coordinates - p.x = p.x * (width / 2); - p.y = p.y * (-height / 2); - - return p; - }, - - /** - * Transforms WebGL coordinates into client coordinates. Reverse of - * `transformClientToGraphCoordinates()` - * - * @param {Object} p - a point object with `x` and `y` attributes, which - * represents a layout coordinate. This method mutates p. - */ - transformGraphToClientCoordinates: function (p) { - // TODO: could be a problem when container has margins? - // transform from graph coordinates - p.x = p.x / (width / 2); - p.y = p.y / (-height / 2); - - // apply transform - p.x = (p.x * transform[0]) + transform[12]; - p.y = (p.y * transform[5]) + transform[13]; - - // denormalize - p.x = ((p.x + 1) * width) / 2; - p.y = ((1 - p.y) * height) / 2; - - return p; - }, - - getNodeAtClientPos: function (clientPos, preciseCheck) { - if (typeof preciseCheck !== "function") { - // we don't know anything about your node structure here :( - // potentially this could be delegated to node program, but for - // right now, we are giving up if you don't pass boundary check - // callback. It answers to a question is nodeUI covers (x, y) - return null; - } - // first transform to graph coordinates: - this.transformClientToGraphCoordinates(clientPos); - // now using precise check iterate over each node and find one within box: - // TODO: This is poor O(N) performance. - for (var i = 0; i < nodesCount; ++i) { - if (preciseCheck(nodes[i], clientPos.x, clientPos.y)) { - return nodes[i].node; - } - } - return null; - } - }; - - // Let graphics fire events before we return it to the caller. - eventify(graphics); - - return graphics; -} +/** + * @fileOverview Defines a graph renderer that uses WebGL based drawings. + * + * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka + */ + +module.exports = webglGraphics; + +var webglInputManager = require('../Input/webglInputManager.js'); +var webglLinkProgram = require('../WebGL/webglLinkProgram.js'); +var webglNodeProgram = require('../WebGL/webglNodeProgram.js'); +var webglSquare = require('../WebGL/webglSquare.js'); +var webglLine = require('../WebGL/webglLine.js'); +var eventify = require('ngraph.events'); +var merge = require('ngraph.merge'); + +/** + * Performs webgl-based graph rendering. This module does not perform + * layout, but only visualizes nodes and edges of the graph. + * + * @param options - to customize graphics behavior. Currently supported parameter + * enableBlending - true by default, allows to use transparency in node/links colors. + * preserveDrawingBuffer - false by default, tells webgl to preserve drawing buffer. + * See https://www.khronos.org/registry/webgl/specs/1.0/#5.2 + */ + +function webglGraphics(options) { + options = merge(options, { + enableBlending : true, + preserveDrawingBuffer : false, + clearColor: false, + clearColorValue : { + r : 1, + g : 1, + b : 1, + a : 1 + } + }); + + var container, + graphicsRoot, + gl, + width, + height, + nodesCount = 0, + linksCount = 0, + transform = [ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + ], + userPlaceNodeCallback, + userPlaceLinkCallback, + nodes = [], + links = [], + initCallback, + + allNodes = {}, + allLinks = {}, + linkProgram = webglLinkProgram(), + nodeProgram = webglNodeProgram(), +/*jshint unused: false */ + nodeUIBuilder = function (node) { + return webglSquare(); // Just make a square, using provided gl context (a nodeProgram); + }, + + linkUIBuilder = function (link) { + return webglLine(0xb3b3b3ff); + }, +/*jshint unused: true */ + updateTransformUniform = function () { + linkProgram.updateTransform(transform); + nodeProgram.updateTransform(transform); + }, + + resetScaleInternal = function () { + transform = [1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]; + }, + + updateSize = function () { + if (container && graphicsRoot) { + width = graphicsRoot.width = Math.max(container.offsetWidth, 1); + height = graphicsRoot.height = Math.max(container.offsetHeight, 1); + if (gl) { gl.viewport(0, 0, width, height); } + if (linkProgram) { linkProgram.updateSize(width / 2, height / 2); } + if (nodeProgram) { nodeProgram.updateSize(width / 2, height / 2); } + } + }, + + fireRescaled = function (graphics) { + graphics.fire("rescaled"); + }; + + graphicsRoot = window.document.createElement("canvas"); + + var graphics = { + getLinkUI: function (linkId) { + return allLinks[linkId]; + }, + + getNodeUI: function (nodeId) { + return allNodes[nodeId]; + }, + + /** + * Sets the callback that creates node representation. + * + * @param builderCallback a callback function that accepts graph node + * as a parameter and must return an element representing this node. + * + * @returns If builderCallbackOrNode is a valid callback function, instance of this is returned; + * Otherwise undefined value is returned + */ + node : function (builderCallback) { + if (typeof builderCallback !== "function") { + return; // todo: throw? This is not compatible with old versions + } + + nodeUIBuilder = builderCallback; + + return this; + }, + + /** + * Sets the callback that creates link representation + * + * @param builderCallback a callback function that accepts graph link + * as a parameter and must return an element representing this link. + * + * @returns If builderCallback is a valid callback function, instance of this is returned; + * Otherwise undefined value is returned. + */ + link : function (builderCallback) { + if (typeof builderCallback !== "function") { + return; // todo: throw? This is not compatible with old versions + } + + linkUIBuilder = builderCallback; + return this; + }, + + + /** + * Allows to override default position setter for the node with a new + * function. newPlaceCallback(nodeUI, position) is function which + * is used by updateNodePosition(). + */ + placeNode : function (newPlaceCallback) { + userPlaceNodeCallback = newPlaceCallback; + return this; + }, + + placeLink : function (newPlaceLinkCallback) { + userPlaceLinkCallback = newPlaceLinkCallback; + return this; + }, + + /** + * Custom input manager listens to mouse events to process nodes drag-n-drop inside WebGL canvas + */ + inputManager : webglInputManager, + + /** + * Called every time before renderer starts rendering. + */ + beginRender : function () { + // this function could be replaced by this.init, + // based on user options. + }, + + /** + * Called every time when renderer finishes one step of rendering. + */ + endRender : function () { + if (linksCount > 0) { + linkProgram.render(); + } + if (nodesCount > 0) { + nodeProgram.render(); + } + }, + + bringLinkToFront : function (linkUI) { + var frontLinkId = linkProgram.getFrontLinkId(), + srcLinkId, + temp; + + linkProgram.bringToFront(linkUI); + + if (frontLinkId > linkUI.id) { + srcLinkId = linkUI.id; + + temp = links[frontLinkId]; + links[frontLinkId] = links[srcLinkId]; + links[frontLinkId].id = frontLinkId; + links[srcLinkId] = temp; + links[srcLinkId].id = srcLinkId; + } + }, + + /** + * Sets translate operation that should be applied to all nodes and links. + */ + graphCenterChanged : function (x, y) { + transform[12] = (2 * x / width) - 1; + transform[13] = 1 - (2 * y / height); + updateTransformUniform(); + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render given link of the graph + * + * @param link - model of a link + */ + addLink: function (link, boundPosition) { + var uiid = linksCount++, + ui = linkUIBuilder(link); + ui.id = uiid; + ui.pos = boundPosition; + + linkProgram.createLink(ui); + + links[uiid] = ui; + allLinks[link.id] = ui; + return ui; + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render given node of the graph. + * + * @param nodeUI visual representation of the node created by node() execution. + **/ + addNode : function (node, boundPosition) { + var uiid = nodesCount++, + ui = nodeUIBuilder(node); + + ui.id = uiid; + ui.position = boundPosition; + ui.node = node; + + nodeProgram.createNode(ui); + + nodes[uiid] = ui; + allNodes[node.id] = ui; + return ui; + }, + + translateRel : function (dx, dy) { + transform[12] += (2 * transform[0] * dx / width) / transform[0]; + transform[13] -= (2 * transform[5] * dy / height) / transform[5]; + updateTransformUniform(); + }, + + scale : function (scaleFactor, scrollPoint) { + // Transform scroll point to clip-space coordinates: + var cx = 2 * scrollPoint.x / width - 1, + cy = 1 - (2 * scrollPoint.y) / height; + + cx -= transform[12]; + cy -= transform[13]; + + transform[12] += cx * (1 - scaleFactor); + transform[13] += cy * (1 - scaleFactor); + + transform[0] *= scaleFactor; + transform[5] *= scaleFactor; + + updateTransformUniform(); + fireRescaled(this); + + return transform[0]; + }, + + resetScale : function () { + resetScaleInternal(); + + if (gl) { + updateSize(); + // TODO: what is this? + // gl.useProgram(linksProgram); + // gl.uniform2f(linksProgram.screenSize, width, height); + updateTransformUniform(); + } + return this; + }, + + /** + * Resizes the graphic without resetting the scale. + * Useful with viva graph in a dynamic container + */ + updateSize: updateSize, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider prepare to render. + */ + init : function (c) { + var contextParameters = {}; + + if (options.preserveDrawingBuffer) { + contextParameters.preserveDrawingBuffer = true; + } + + container = c; + + updateSize(); + resetScaleInternal(); + container.appendChild(graphicsRoot); + + + gl = graphicsRoot.getContext("experimental-webgl", contextParameters); + if (!gl) { + var msg = "Could not initialize WebGL. Seems like the browser doesn't support it."; + window.alert(msg); + throw msg; + } + if (options.enableBlending) { + gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); + gl.enable(gl.BLEND); + } + if (options.clearColor) { + var color = options.clearColorValue; + gl.clearColor(color.r, color.g, color.b, color.a); + // TODO: not the best way, really. Should come up with something better + // what if we need more updates inside beginRender, like depth buffer? + this.beginRender = function () { + gl.clear(gl.COLOR_BUFFER_BIT); + }; + } + + linkProgram.load(gl); + linkProgram.updateSize(width / 2, height / 2); + + nodeProgram.load(gl); + nodeProgram.updateSize(width / 2, height / 2); + + updateTransformUniform(); + + // Notify the world if someone waited for update. TODO: should send an event + if (typeof initCallback === "function") { + initCallback(graphicsRoot); + } + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider release occupied resources. + */ + release : function (container) { + if (graphicsRoot && container) { + container.removeChild(graphicsRoot); + // TODO: anything else? + } + }, + + /** + * Checks whether webgl is supported by this browser. + */ + isSupported : function () { + var c = window.document.createElement("canvas"), + gl = c && c.getContext && c.getContext("experimental-webgl"); + return gl; + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider remove link from rendering surface. + * + * @param linkUI visual representation of the link created by link() execution. + **/ + releaseLink : function (link) { + if (linksCount > 0) { linksCount -= 1; } + var linkUI = allLinks[link.id]; + delete allLinks[link.id]; + + linkProgram.removeLink(linkUI); + + var linkIdToRemove = linkUI.id; + if (linkIdToRemove < linksCount) { + if (linksCount === 0 || linksCount === linkIdToRemove) { + return; // no more links or removed link is the last one. + } + + var lastLinkUI = links[linksCount]; + links[linkIdToRemove] = lastLinkUI; + lastLinkUI.id = linkIdToRemove; + } + }, + + /** + * Called by Viva.Graph.View.renderer to let concrete graphic output + * provider remove node from rendering surface. + * + * @param nodeUI visual representation of the node created by node() execution. + **/ + releaseNode : function (node) { + if (nodesCount > 0) { nodesCount -= 1; } + var nodeUI = allNodes[node.id]; + delete allNodes[node.id]; + + nodeProgram.removeNode(nodeUI); + + var nodeIdToRemove = nodeUI.id; + if (nodeIdToRemove < nodesCount) { + if (nodesCount === 0 || nodesCount === nodeIdToRemove) { + return; // no more nodes or removed node is the last in the list. + } + + var lastNodeUI = nodes[nodesCount]; + + nodes[nodeIdToRemove] = lastNodeUI; + lastNodeUI.id = nodeIdToRemove; + + // Since concrete shaders may cache properties in the UI element + // we are letting them to make this swap (e.g. image node shader + // uses this approach to update node's offset in the atlas) + nodeProgram.replaceProperties(nodeUI, lastNodeUI); + } + }, + + renderNodes: function () { + var pos = {x : 0, y : 0}; + // WebGL coordinate system is different. Would be better + // to have this transform in the shader code, but it would + // require every shader to be updated.. + for (var i = 0; i < nodesCount; ++i) { + var ui = nodes[i]; + pos.x = ui.position.x; + pos.y = ui.position.y; + if (userPlaceNodeCallback) { + userPlaceNodeCallback(ui, pos); + } + + nodeProgram.position(ui, pos); + } + }, + + renderLinks: function () { + if (this.omitLinksRendering) { return; } + + var toPos = {x : 0, y : 0}; + var fromPos = {x : 0, y : 0}; + for (var i = 0; i < linksCount; ++i) { + var ui = links[i]; + var pos = ui.pos.from; + fromPos.x = pos.x; + fromPos.y = -pos.y; + pos = ui.pos.to; + toPos.x = pos.x; + toPos.y = -pos.y; + if (userPlaceLinkCallback) { + userPlaceLinkCallback(ui, fromPos, toPos); + } + + linkProgram.position(ui, fromPos, toPos); + } + }, + + /** + * Returns root element which hosts graphics. + */ + getGraphicsRoot : function (callbackWhenReady) { + // todo: should fire an event, instead of having this context. + if (typeof callbackWhenReady === "function") { + if (graphicsRoot) { + callbackWhenReady(graphicsRoot); + } else { + initCallback = callbackWhenReady; + } + } + return graphicsRoot; + }, + + /** + * Updates default shader which renders nodes + * + * @param newProgram to use for nodes. + */ + setNodeProgram : function (newProgram) { + if (!gl && newProgram) { + // Nothing created yet. Just set shader to the new one + // and let initialization logic take care about the rest. + nodeProgram = newProgram; + } else if (newProgram) { + throw "Not implemented. Cannot swap shader on the fly... Yet."; + // TODO: unload old shader and reinit. + } + }, + + /** + * Updates default shader which renders links + * + * @param newProgram to use for links. + */ + setLinkProgram : function (newProgram) { + if (!gl && newProgram) { + // Nothing created yet. Just set shader to the new one + // and let initialization logic take care about the rest. + linkProgram = newProgram; + } else if (newProgram) { + throw "Not implemented. Cannot swap shader on the fly... Yet."; + // TODO: unload old shader and reinit. + } + }, + + /** + * Transforms client coordinates into layout coordinates. Client coordinates + * are DOM coordinates relative to the rendering container. Layout + * coordinates are those assigned by by layout algorithm to each node. + * + * @param {Object} p - a point object with `x` and `y` attributes. + * This method mutates p. + */ + transformClientToGraphCoordinates: function (p) { + // TODO: could be a problem when container has margins? + // normalize + p.x = ((2 * p.x) / width) - 1; + p.y = 1 - ((2 * p.y) / height); + + // apply transform + p.x = (p.x - transform[12]) / transform[0]; + p.y = (p.y - transform[13]) / transform[5]; + + // transform to graph coordinates + p.x = p.x * (width / 2); + p.y = p.y * (-height / 2); + + return p; + }, + + /** + * Transforms WebGL coordinates into client coordinates. Reverse of + * `transformClientToGraphCoordinates()` + * + * @param {Object} p - a point object with `x` and `y` attributes, which + * represents a layout coordinate. This method mutates p. + */ + transformGraphToClientCoordinates: function (p) { + // TODO: could be a problem when container has margins? + // transform from graph coordinates + p.x = p.x / (width / 2); + p.y = p.y / (-height / 2); + + // apply transform + p.x = (p.x * transform[0]) + transform[12]; + p.y = (p.y * transform[5]) + transform[13]; + + // denormalize + p.x = ((p.x + 1) * width) / 2; + p.y = ((1 - p.y) * height) / 2; + + return p; + }, + + getNodeAtClientPos: function (clientPos, preciseCheck) { + if (typeof preciseCheck !== "function") { + // we don't know anything about your node structure here :( + // potentially this could be delegated to node program, but for + // right now, we are giving up if you don't pass boundary check + // callback. It answers to a question is nodeUI covers (x, y) + return null; + } + // first transform to graph coordinates: + this.transformClientToGraphCoordinates(clientPos); + // now using precise check iterate over each node and find one within box: + // TODO: This is poor O(N) performance. + for (var i = 0; i < nodesCount; ++i) { + if (preciseCheck(nodes[i], clientPos.x, clientPos.y)) { + return nodes[i].node; + } + } + return null; + } + }; + + // Let graphics fire events before we return it to the caller. + eventify(graphics); + + return graphics; +} },{"../Input/webglInputManager.js":36,"../WebGL/webglLine.js":58,"../WebGL/webglLinkProgram.js":59,"../WebGL/webglNodeProgram.js":60,"../WebGL/webglSquare.js":61,"ngraph.events":7,"ngraph.merge":13}],51:[function(require,module,exports){ module.exports = parseColor; diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index bd2b3f4..3e2be0b 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,2 @@ !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=s*d-f*c,0===y?null:(x=y<0?-y/2:y/2,x=0,w=c*p-d*l,b.x=(w<0?w-x:w+x)/y,w=f*l-s*p,b.y=(w<0?w-x:w+x)/y,b)))}n.exports=r},{}],4:[function(e,n,t){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":5,"./src/degree.js":6}],5:[function(e,n,t){function r(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;i0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function f(e,n,t){if(e<1||n<1||t<1)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=p();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;i0&&a.addLink(s,r-1+o*e+u),o>0&&a.addLink(s,r+(o-1)*e+u),i>0&&a.addLink(s,r+o*e+(i-1)*e*n)}return a}function c(e){if(e<0)throw new Error("Invalid number of nodes in balanced tree");var n,t=p(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;n= 0");var n,t=p();for(n=0;n=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,u=e("ngraph.random").random(o||42),s=p();for(i=0;i=0&&t.links.splice(n,1)),r&&(n=o(e,r.links),n>=0&&r.links.splice(n,1)),U(e,"remove"),F(),!0}function h(e,n){var t,r=f(e);if(!r)return null;for(t=0;t0&&(O.fire("changed",M),M.length=0)}function P(){return Object.keys?k:j}function k(e){if("function"==typeof e)for(var n=Object.keys(A),t=0;t=0?i:-1,o);return v.push(a),a},getTotalMovement:function(){return x},removeSpring:function(e){if(e){var n=v.indexOf(e);return n>-1?(v.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return h.getBestNewPosition(e)},getBBox:function(){return h.box},gravity:function(e){return void 0!==e?(n.gravity=e,g.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,g.options({theta:e}),this):n.theta}};return o(n,w),a(w),w}n.exports=r},{"./lib/bounds":16,"./lib/createBody":17,"./lib/dragForce":18,"./lib/eulerIntegrator":19,"./lib/spring":20,"./lib/springForce":21,"ngraph.events":7,"ngraph.expose":8,"ngraph.merge":13,"ngraph.quadtreebh":22}],16:[function(e,n,t){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;u1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/u}n.exports=r},{}],20:[function(e,n,t){function r(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=r},{}],21:[function(e,n,t){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":8,"ngraph.merge":13,"ngraph.random":26}],22:[function(e,n,t){function r(e,n){return 0===n?e.quad0:1===n?e.quad1:2===n?e.quad2:3===n?e.quad3:null}function o(e,n,t){0===n?e.quad0=t:1===n?e.quad1=t:2===n?e.quad2=t:3===n&&(e.quad3=t)}n.exports=function(n){function t(){var e=h[m];return e?(e.quad0=null,e.quad1=null,e.quad2=null,e.quad3=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0):(e=new f,h[m]=e),++m,e}function i(e){var n,t,r,o,i=p,a=0,u=0,f=1,c=0,d=1;for(i[0]=y;f;){var v=i[c],h=v.body;f-=1,c+=1;var m=h!==e;h&&m?(t=h.pos.x-e.pos.x,r=h.pos.y-e.pos.y,o=Math.sqrt(t*t+r*r),0===o&&(t=(s.nextDouble()-.5)/50,r=(s.nextDouble()-.5)/50,o=Math.sqrt(t*t+r*r)),n=l*h.mass*e.mass/(o*o*o),a+=n*t,u+=n*r):m&&(t=v.massX/v.mass-e.pos.x,r=v.massY/v.mass-e.pos.y,o=Math.sqrt(t*t+r*r),0===o&&(t=(s.nextDouble()-.5)/50,r=(s.nextDouble()-.5)/50,o=Math.sqrt(t*t+r*r)),(v.right-v.left)/oi&&(i=f),ca&&(a=c)}var d=i-r,l=a-o;for(d>l?a=o+d:i=r+l,m=0,y=t(),y.left=r,y.right=i,y.top=o,y.bottom=a,n=s-1,n>=0&&(y.body=e[n]);n--;)u(e[n],y)}function u(e){for(v.reset(),v.push(y,e);!v.isEmpty();){var n=v.pop(),i=n.node,a=n.body;if(i.body){var u=i.body;if(i.body=null,d(u.pos,a.pos)){var f=3;do{var c=s.nextDouble(),l=(i.right-i.left)*c,p=(i.bottom-i.top)*c;u.pos.x=i.left+l,u.pos.y=i.top+p,f-=1}while(f>0&&d(u.pos,a.pos));if(0===f&&d(u.pos,a.pos))return}v.push(i,u),v.push(i,a)}else{var g=a.pos.x,h=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*g,i.massY=i.massY+a.mass*h;var m=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;g>w&&(m+=1,x=w,w=i.right),h>E&&(m+=2,b=E,E=i.bottom);var L=r(i,m);L?v.push(L,a):(L=t(),L.left=x,L.top=b,L.right=w,L.bottom=E,L.body=a,o(i,m,L))}}}n=n||{},n.gravity="number"==typeof n.gravity?n.gravity:-1,n.theta="number"==typeof n.theta?n.theta:.8;var s=e("ngraph.random").random(1984),f=e("./node"),c=e("./insertStack"),d=e("./isSamePosition"),l=n.gravity,p=[],v=new c,g=n.theta,h=[],m=0,y=t();return{insertBodies:a,getRoot:function(){return y},updateBodyForce:i,options:function(e){return e?("number"==typeof e.gravity&&(l=e.gravity),"number"==typeof e.theta&&(g=e.theta),this):{gravity:l,theta:g}}}}},{"./insertStack":23,"./isSamePosition":24,"./node":25,"ngraph.random":26}],23:[function(e,n,t){function r(){this.stack=[],this.popIdx=0}function o(e,n){this.node=e,this.body=n}n.exports=r,r.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new o(e,n),++this.popIdx},pop:function(){if(this.popIdx>0)return this.stack[--this.popIdx]},reset:function(){this.popIdx=0}}},{}],24:[function(e,n,t){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return t<1e-8&&r<1e-8}},{}],25:[function(e,n,t){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],26:[function(e,n,t){function r(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function o(e,n){var t=n||r();if("function"!=typeof t.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var r,o,i;for(r=e.length-1;r>0;--r)o=t.next(r+1),i=e[o],e[o]=e[r],e[r]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,r,o;for(n=e.length-1;n>0;--n)r=t.next(n+1),o=e[r],e[r]=e[n],e[n]=o;return e}}}n.exports={random:r,randomIterator:o}},{}],27:[function(e,n,t){function r(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=r},{}],28:[function(e,n,t){function r(e,n){var t=o(e);if(void 0===n)return t;for(var r=Object.keys(n),i=0;iv&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},j=function(e){p=!1,o.off("touchmove",k),o.off("touchend",j),o.off("touchcancel",j),c=null,r&&r(e)},A=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,o.on("touchmove",k),o.on("touchend",j),o.on("touchcancel",j))},_=function(e){return 1===e.touches.length?A(e,e.touches[0]):void(2===e.touches.length&&(m(e), -y(e),v=P(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),o.off("mousemove",w),o.off("mouseup",E),o.off("touchmove",k),o.off("touchend",j),o.off("touchcancel",j),N(null)}}}n.exports=r;var o=e("../Utils/documentEvents.js"),i=e("../Utils/browserInfo.js"),a=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":39,"../Utils/documentEvents.js":40,"../Utils/findElementPosition.js":41}],36:[function(e,n,t){function r(e,n){var t=o(n),r=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){r=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(r);var o=i[e.id];return o&&o.onStart&&o.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(r),r=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(r){var t=i[r.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=r;var o=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":57}],37:[function(e,n,t){function r(e,n){function t(e){return d[e]}n=o(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var r=i(n.seed),u=new a(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(e){return{x:r.next(n.maxX),y:r.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"!=typeof z||z}function r(){G=G||window.document.body,F=F||i(e,{springLength:80,springCoeff:2e-4}),O=O||a(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||s)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return W=F.step()&&!H,l(),!W}function v(e){return R?void(V+=e):void(e?(V+=e,R=f(function(){return p()},M)):(X=0,V=0,R=f(p,M)))}function g(){J||(W=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;e0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):r=e),t},getSvgRoot:function(){return t}};return i(b),b}n.exports=r;var o=e("simplesvg"),i=e("ngraph.events"),a=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":34,"ngraph.events":7,simplesvg:28}],50:[function(e,n,t){function r(e){e=c(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,r,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=i(),N=a(),P=function(e){return u()},k=function(e){return s(3014898687)},j=function(){L.updateTransform(y),N.updateTransform(y)},A=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),r&&r.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),N&&N.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){if("function"==typeof e)return P=e,this},link:function(e){if("function"==typeof e)return k=e,this},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:o,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&N.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,j()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=P(e);return r.id=t,r.position=n,r.node=e,N.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],j()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,j(),I(this),y[0]},resetScale:function(){return A(),r&&(_(),j()),this},updateSize:_,init:function(o){var i={};if(e.preserveDrawingBuffer&&(i.preserveDrawingBuffer=!0),n=o,_(),A(),n.appendChild(t),r=t.getContext("experimental-webgl",i),!r){var a="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(a),a}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var u=e.clearColorValue;r.clearColor(u.r,u.g,u.b,u.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}L.load(r),L.updateSize(d/2,l/2),N.load(r),N.updateSize(d/2,l/2),j(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(t0&&(h-=1);var n=b[e.id];delete b[e.id],N.removeNode(n);var t=n.id;if(te.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;o=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!o(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:r,getCoordinates:a,load:u};return E}function o(e){return 0===(e&e-1)}var i=e("./texture.js");n.exports=r},{"./texture.js":52}],55:[function(e,n,t){function r(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=r},{}],56:[function(e,n,t){function r(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(A-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*N,A*N,N))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*A)}var v,g,h,m,y,x,w,b,E,L,N=18,P=o(),k=i(),j=1024,A=0,_=new Float32Array(64);return{load:t,position:r,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function o(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function i(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var a=e("./webglAtlas.js"),u=e("./webgl.js");n.exports=r},{"./webgl.js":53,"./webglAtlas.js":54}],57:[function(e,n,t){function r(e){function n(){x=null}function t(e){x=e}function r(e){return"function"==typeof e&&k.push(e),A}function i(e){return"function"==typeof e&&P.push(e),A}function a(e){return"function"==typeof e&&N.push(e),A}function u(e){return"function"==typeof e&&L.push(e),A}function s(e){return"function"==typeof e&&E.push(e),A}function f(e){return"function"==typeof e&&b.push(e),A}function c(e){return"function"==typeof e&&w.push(e),A}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oh.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,r=o(a),e=r.createProgram(v,p),n.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&r.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&r.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],60:[function(e,n,t){function r(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(P),N=n,P=t,L=e}}function n(e){d=e,v=o(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;N[t*x]=n.x,N[t*x+1]=-n.y,N[t*x+2]=e.size,P[t*x+3]=e.color}function r(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(P,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),N=new Float32Array(L),P=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:r,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],61:[function(e,n,t){function r(e,n){return{size:"number"==typeof e?e:10,color:o(n)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],62:[function(e,n,t){n.exports="0.8.1"},{}]},{},[1])(1)}); \ No newline at end of file +y(e),v=P(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),o.off("mousemove",w),o.off("mouseup",E),o.off("touchmove",k),o.off("touchend",j),o.off("touchcancel",j),N(null)}}}n.exports=r;var o=e("../Utils/documentEvents.js"),i=e("../Utils/browserInfo.js"),a=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":39,"../Utils/documentEvents.js":40,"../Utils/findElementPosition.js":41}],36:[function(e,n,t){function r(e,n){var t=o(n),r=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){r=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(r);var o=i[e.id];return o&&o.onStart&&o.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(r),r=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(r){var t=i[r.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=r;var o=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":57}],37:[function(e,n,t){function r(e,n){function t(e){return d[e]}n=o(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var r=i(n.seed),u=new a(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(e){return{x:r.next(n.maxX),y:r.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"!=typeof z||z}function r(){G=G||window.document.body,F=F||i(e,{springLength:80,springCoeff:2e-4}),O=O||a(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||s)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return X=F.step()&&!V,l(),!X}function v(e){R||(R=void 0!==e?f(function(){if(e-=1,e<0){var n=!1;return n}return p()},M):f(p,M))}function g(){W||(X=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;e0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):r=e),t},getSvgRoot:function(){return t}};return i(b),b}n.exports=r;var o=e("simplesvg"),i=e("ngraph.events"),a=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":34,"ngraph.events":7,simplesvg:28}],50:[function(e,n,t){function r(e){e=c(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,r,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=i(),N=a(),P=function(e){return u()},k=function(e){return s(3014898687)},j=function(){L.updateTransform(y),N.updateTransform(y)},A=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),r&&r.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),N&&N.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){if("function"==typeof e)return P=e,this},link:function(e){if("function"==typeof e)return k=e,this},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:o,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&N.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,j()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=P(e);return r.id=t,r.position=n,r.node=e,N.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],j()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,j(),I(this),y[0]},resetScale:function(){return A(),r&&(_(),j()),this},updateSize:_,init:function(o){var i={};if(e.preserveDrawingBuffer&&(i.preserveDrawingBuffer=!0),n=o,_(),A(),n.appendChild(t),r=t.getContext("experimental-webgl",i),!r){var a="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(a),a}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var u=e.clearColorValue;r.clearColor(u.r,u.g,u.b,u.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}L.load(r),L.updateSize(d/2,l/2),N.load(r),N.updateSize(d/2,l/2),j(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(t0&&(h-=1);var n=b[e.id];delete b[e.id],N.removeNode(n);var t=n.id;if(te.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;o=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!o(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:r,getCoordinates:a,load:u};return E}function o(e){return 0===(e&e-1)}var i=e("./texture.js");n.exports=r},{"./texture.js":52}],55:[function(e,n,t){function r(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=r},{}],56:[function(e,n,t){function r(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(A-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*N,A*N,N))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*A)}var v,g,h,m,y,x,w,b,E,L,N=18,P=o(),k=i(),j=1024,A=0,_=new Float32Array(64);return{load:t,position:r,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function o(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function i(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var a=e("./webglAtlas.js"),u=e("./webgl.js");n.exports=r},{"./webgl.js":53,"./webglAtlas.js":54}],57:[function(e,n,t){function r(e){function n(){x=null}function t(e){x=e}function r(e){return"function"==typeof e&&k.push(e),A}function i(e){return"function"==typeof e&&P.push(e),A}function a(e){return"function"==typeof e&&N.push(e),A}function u(e){return"function"==typeof e&&L.push(e),A}function s(e){return"function"==typeof e&&E.push(e),A}function f(e){return"function"==typeof e&&b.push(e),A}function c(e){return"function"==typeof e&&w.push(e),A}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oh.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,r=o(a),e=r.createProgram(v,p),n.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&r.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&r.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],60:[function(e,n,t){function r(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(P),N=n,P=t,L=e}}function n(e){d=e,v=o(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;N[t*x]=n.x,N[t*x+1]=-n.y,N[t*x+2]=e.size,P[t*x+3]=e.color}function r(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(P,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),N=new Float32Array(L),P=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:r,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],61:[function(e,n,t){function r(e,n){return{size:"number"==typeof e?e:10,color:o(n)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],62:[function(e,n,t){n.exports="0.8.1"},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/src/View/renderer.js b/src/View/renderer.js index 5a6baae..a73fab9 100644 --- a/src/View/renderer.js +++ b/src/View/renderer.js @@ -85,7 +85,7 @@ function renderer(graph, settings) { * Performs rendering of the graph. * * @param iterationsCount if specified renderer will run only given number of iterations - * and then stop. Otherwise graph rendering is performed infinitely. + * and then stop. Otherwise graph rendering is performed indefinitely. * * Note: if rendering stopped by used started dragging nodes or new nodes were added to the * graph renderer will give run more iterations to reflect changes. @@ -137,6 +137,13 @@ function renderer(graph, settings) { return scale(false); }, + /** + * Returns current transformation matrix. + */ + getTransform: function() { + return transform; + }, + /** * Centers renderer at x,y graph's coordinates */ From 9b4d1e58a61af123191ea3ad04d0e803cdf9a5d4 Mon Sep 17 00:00:00 2001 From: Andriy Kashcha Date: Thu, 1 Mar 2018 21:21:09 -0800 Subject: [PATCH 245/276] 0.10.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 260c84e..5d8ea11 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.10.0", + "version": "0.10.1", "description": "Graph Drawing Library", "main": "src/viva", "directories": { From 6c8506f83daaf3c6486bdd2308741f3b05767af0 Mon Sep 17 00:00:00 2001 From: Andriy Kashcha Date: Tue, 6 Mar 2018 20:53:58 -0800 Subject: [PATCH 246/276] Allow to fetch current layout object --- src/View/renderer.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/View/renderer.js b/src/View/renderer.js index a73fab9..16a4eb6 100644 --- a/src/View/renderer.js +++ b/src/View/renderer.js @@ -38,7 +38,7 @@ var dragndrop = require('../Input/dragndrop.js'); * * // Layout algorithm to be used. The algorithm is expected to comply with defined * // interface and is expected to be iterative. Renderer will use it then to calculate - * // grpaph's layout. For examples of the interface refer to Viva.Graph.Layout.forceDirected() + * // graph's layout. For examples of the interface refer to Viva.Graph.Layout.forceDirected() * layout : Viva.Graph.Layout.forceDirected(), * * // Directs renderer to display links. Usually rendering links is the slowest part of this @@ -158,6 +158,13 @@ function renderer(graph, settings) { getGraphics: function() { return graphics; }, + + /** + * Gets current layout. + */ + getLayout: function() { + return layout; + }, /** * Removes this renderer and deallocates all resources/timers From 9fe681191a8453b8dc5cdbcbd3d326a86dcb90c4 Mon Sep 17 00:00:00 2001 From: Andriy Kashcha Date: Tue, 6 Mar 2018 20:54:11 -0800 Subject: [PATCH 247/276] updated dependencies --- dist/vivagraph.js | 1011 ++++++++++++++++++++++++++++------------- dist/vivagraph.min.js | 5 +- package.json | 12 +- 3 files changed, 704 insertions(+), 324 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 1217d7a..7934f28 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -112,7 +112,7 @@ Viva.Graph = { module.exports = Viva; -},{"./Algorithms/centrality.js":32,"./Algorithms/operations.js":33,"./Input/domInputManager.js":34,"./Input/dragndrop.js":35,"./Input/webglInputManager.js":36,"./Layout/constant.js":37,"./Utils/backwardCompatibleEvents.js":38,"./Utils/browserInfo.js":39,"./Utils/findElementPosition.js":41,"./Utils/getDimensions.js":42,"./Utils/intersectRect.js":43,"./Utils/rect.js":45,"./Utils/timer.js":46,"./View/renderer.js":48,"./View/svgGraphics.js":49,"./View/webglGraphics.js":50,"./WebGL/parseColor.js":51,"./WebGL/texture.js":52,"./WebGL/webgl.js":53,"./WebGL/webglAtlas.js":54,"./WebGL/webglImage.js":55,"./WebGL/webglImageNodeProgram.js":56,"./WebGL/webglInputEvents.js":57,"./WebGL/webglLine.js":58,"./WebGL/webglLinkProgram.js":59,"./WebGL/webglNodeProgram.js":60,"./WebGL/webglSquare.js":61,"./version.js":62,"gintersect":3,"ngraph.events":7,"ngraph.forcelayout":9,"ngraph.fromjson":10,"ngraph.generators":11,"ngraph.graph":12,"ngraph.merge":13,"ngraph.random":26,"ngraph.tojson":27,"simplesvg":28}],2:[function(require,module,exports){ +},{"./Algorithms/centrality.js":36,"./Algorithms/operations.js":37,"./Input/domInputManager.js":38,"./Input/dragndrop.js":39,"./Input/webglInputManager.js":40,"./Layout/constant.js":41,"./Utils/backwardCompatibleEvents.js":42,"./Utils/browserInfo.js":43,"./Utils/findElementPosition.js":45,"./Utils/getDimensions.js":46,"./Utils/intersectRect.js":47,"./Utils/rect.js":49,"./Utils/timer.js":50,"./View/renderer.js":52,"./View/svgGraphics.js":53,"./View/webglGraphics.js":54,"./WebGL/parseColor.js":55,"./WebGL/texture.js":56,"./WebGL/webgl.js":57,"./WebGL/webglAtlas.js":58,"./WebGL/webglImage.js":59,"./WebGL/webglImageNodeProgram.js":60,"./WebGL/webglInputEvents.js":61,"./WebGL/webglLine.js":62,"./WebGL/webglLinkProgram.js":63,"./WebGL/webglNodeProgram.js":64,"./WebGL/webglSquare.js":65,"./version.js":66,"gintersect":3,"ngraph.events":9,"ngraph.forcelayout":11,"ngraph.fromjson":13,"ngraph.generators":14,"ngraph.graph":16,"ngraph.merge":17,"ngraph.random":30,"ngraph.tojson":31,"simplesvg":32}],2:[function(require,module,exports){ addEventListener.removeEventListener = removeEventListener addEventListener.addEventListener = addEventListener @@ -264,8 +264,10 @@ function intersect( },{}],4:[function(require,module,exports){ module.exports.degree = require('./src/degree.js'); module.exports.betweenness = require('./src/betweenness.js'); +module.exports.closeness = require('./src/closeness.js'); +module.exports.eccentricity = require('./src/eccentricity.js'); -},{"./src/betweenness.js":5,"./src/degree.js":6}],5:[function(require,module,exports){ +},{"./src/betweenness.js":5,"./src/closeness.js":6,"./src/degree.js":7,"./src/eccentricity.js":8}],5:[function(require,module,exports){ module.exports = betweennes; /** @@ -340,7 +342,6 @@ function betweennes(graph, oriented) { while (Q.length) { var v = Q.shift(); - var dedup = Object.create(null); S.push(v); graph.forEachLinkedNode(v, toId, oriented); } @@ -378,6 +379,78 @@ function betweennes(graph, oriented) { } },{}],6:[function(require,module,exports){ +module.exports = closeness; + +/** + * In a connected graph, the normalized closeness centrality of a node is the average + * length of the shortest path between the node and all other nodes in the + * graph. Thus the more central a node is, the closer it is to all other nodes. + */ +function closeness(graph, oriented) { + var Q = []; + // list of predcessors on shortest paths from source + // distance from source + var dist = Object.create(null); + + var currentNode; + var centrality = Object.create(null); + + graph.forEachNode(setCentralityToZero); + graph.forEachNode(calculateCentrality); + + return centrality; + + function setCentralityToZero(node) { + centrality[node.id] = 0; + } + + function calculateCentrality(node) { + currentNode = node.id; + singleSourceShortestPath(currentNode); + accumulate(); + } + + function accumulate() { + // Add all distances for node to array, excluding -1s + var distances = Object.keys(dist).map(function(key) {return dist[key]}).filter(function(val){return val !== -1}); + // Set number of reachable nodes + var reachableNodesTotal = distances.length; + // Compute sum of all distances for node + var totalDistance = distances.reduce(function(a,b) { return a + b }); + if (totalDistance > 0) { + centrality[currentNode] = ((reachableNodesTotal - 1) / totalDistance); + } else { + centrality[currentNode] = 0; + } + } + + function singleSourceShortestPath(source) { + graph.forEachNode(initNode); + dist[source] = 0; + Q.push(source); + + while (Q.length) { + var v = Q.shift(); + graph.forEachLinkedNode(v, processNode, oriented); + } + + function initNode(node) { + var nodeId = node.id; + dist[nodeId] = -1; + } + + function processNode(otherNode) { + var w = otherNode.id + if (dist[w] === -1) { + // Node w is found for the first time + dist[w] = dist[v] + 1; + Q.push(w); + } + } + } +} + +},{}],7:[function(require,module,exports){ module.exports = degree; /** @@ -392,10 +465,8 @@ module.exports = degree; * 'inout' - (default) generic degree centrality is calculated */ function degree(graph, kind) { - var getNodeDegree, - sortedDegrees = [], - result = Object.create(null), - nodeDegree; + var getNodeDegree; + var result = Object.create(null); kind = (kind || 'both').toLowerCase(); if (kind === 'both' || kind === 'inout') { @@ -420,6 +491,8 @@ function degree(graph, kind) { function inDegreeCalculator(links, nodeId) { var total = 0; + if (!links) return total; + for (var i = 0; i < links.length; i += 1) { total += (links[i].toId === nodeId) ? 1 : 0; } @@ -428,6 +501,8 @@ function inDegreeCalculator(links, nodeId) { function outDegreeCalculator(links, nodeId) { var total = 0; + if (!links) return total; + for (var i = 0; i < links.length; i += 1) { total += (links[i].fromId === nodeId) ? 1 : 0; } @@ -435,10 +510,78 @@ function outDegreeCalculator(links, nodeId) { } function inoutDegreeCalculator(links) { + if (!links) return 0; + return links.length; } -},{}],7:[function(require,module,exports){ +},{}],8:[function(require,module,exports){ +module.exports = eccentricity; + +/** + * The eccentricity centrality of a node is the greatest distance between that node and + * any other node in the network. + */ +function eccentricity(graph, oriented) { + var Q = []; + // distance from source + var dist = Object.create(null); + + var currentNode; + var centrality = Object.create(null); + + graph.forEachNode(setCentralityToZero); + graph.forEachNode(calculateCentrality); + + return centrality; + + function setCentralityToZero(node) { + centrality[node.id] = 0; + } + + function calculateCentrality(node) { + currentNode = node.id; + singleSourceShortestPath(currentNode); + accumulate(); + } + + function accumulate() { + var maxDist = 0; + Object.keys(dist).forEach(function (key) { + var val = dist[key]; + if (maxDist < val) maxDist = val; + }); + + centrality[currentNode] = maxDist; + } + + function singleSourceShortestPath(source) { + graph.forEachNode(initNode); + dist[source] = 0; + Q.push(source); + + while (Q.length) { + var v = Q.shift(); + graph.forEachLinkedNode(v, processNode, oriented); + } + + function initNode(node) { + var nodeId = node.id; + dist[nodeId] = -1; + } + + function processNode(otherNode) { + var w = otherNode.id + if (dist[w] === -1) { + // Node w is found for the first time + dist[w] = dist[v] + 1; + Q.push(w); + } + } + } +} + +},{}],9:[function(require,module,exports){ module.exports = function(subject) { validateSubject(subject); @@ -528,7 +671,7 @@ function validateSubject(subject) { } } -},{}],8:[function(require,module,exports){ +},{}],10:[function(require,module,exports){ module.exports = exposeProperties; /** @@ -574,7 +717,7 @@ function augment(source, target, key) { } } -},{}],9:[function(require,module,exports){ +},{}],11:[function(require,module,exports){ module.exports = createLayout; module.exports.simulator = require('ngraph.physics.simulator'); @@ -596,6 +739,11 @@ function createLayout(graph, physicsSettings) { var createSimulator = require('ngraph.physics.simulator'); var physicsSimulator = createSimulator(physicsSettings); + var nodeMass = defaultNodeMass + if (physicsSettings && typeof physicsSettings.nodeMass === 'function') { + nodeMass = physicsSettings.nodeMass + } + var nodeBodies = Object.create(null); var springs = {}; var bodiesCount = 0; @@ -655,6 +803,7 @@ function createLayout(graph, physicsSettings) { setNodePosition: function (nodeId) { var body = getInitializedBody(nodeId); body.setPosition.apply(body, Array.prototype.slice.call(arguments, 1)); + physicsSimulator.invalidateBBox(); }, /** @@ -904,6 +1053,9 @@ function createLayout(graph, physicsSettings) { function updateBodyMass(nodeId) { var body = nodeBodies[nodeId]; body.mass = nodeMass(nodeId); + if (Number.isNaN(body.mass)) { + throw new Error('Node mass should be a number') + } } /** @@ -933,7 +1085,7 @@ function createLayout(graph, physicsSettings) { * @param {String|Number} nodeId identifier of a node, for which body mass needs to be calculated * @returns {Number} recommended mass of the body; */ - function nodeMass(nodeId) { + function defaultNodeMass(nodeId) { var links = graph.getLinks(nodeId); if (!links) return 1; return 1 + links.length / 3.0; @@ -942,7 +1094,9 @@ function createLayout(graph, physicsSettings) { function noop() { } -},{"ngraph.events":7,"ngraph.physics.simulator":15}],10:[function(require,module,exports){ +},{"ngraph.events":12,"ngraph.physics.simulator":19}],12:[function(require,module,exports){ +arguments[4][9][0].apply(exports,arguments) +},{"dup":9}],13:[function(require,module,exports){ module.exports = load; var createGraph = require('ngraph.graph'); @@ -987,312 +1141,479 @@ function load(jsonGraph, nodeTransform, linkTransform) { function id(x) { return x; } -},{"ngraph.graph":12}],11:[function(require,module,exports){ -module.exports = { - ladder: ladder, - complete: complete, - completeBipartite: completeBipartite, - balancedBinTree: balancedBinTree, - path: path, - circularLadder: circularLadder, - grid: grid, - grid3: grid3, - noLinks: noLinks, - wattsStrogatz: wattsStrogatz -}; - +},{"ngraph.graph":16}],14:[function(require,module,exports){ var createGraph = require('ngraph.graph'); -function ladder(n) { -/** - * Ladder graph is a graph in form of ladder - * @param {Number} n Represents number of steps in the ladder - */ - if (!n || n < 0) { - throw new Error("Invalid number of nodes"); - } +module.exports = factory(createGraph); - var g = createGraph(), - i; - - for (i = 0; i < n - 1; ++i) { - g.addLink(i, i + 1); - // first row - g.addLink(n + i, n + i + 1); - // second row - g.addLink(i, n + i); - // ladder's step - } +// Allow other developers have their own createGraph +module.exports.factory = factory; - g.addLink(n - 1, 2 * n - 1); - // last step in the ladder; +function factory(createGraph) { + return { + ladder: ladder, + complete: complete, + completeBipartite: completeBipartite, + balancedBinTree: balancedBinTree, + path: path, + circularLadder: circularLadder, + grid: grid, + grid3: grid3, + noLinks: noLinks, + wattsStrogatz: wattsStrogatz, + cliqueCircle: cliqueCircle + }; - return g; -} -function circularLadder(n) { -/** - * Circular ladder with n steps. - * - * @param {Number} n of steps in the ladder. - */ + function ladder(n) { + /** + * Ladder graph is a graph in form of ladder + * @param {Number} n Represents number of steps in the ladder + */ if (!n || n < 0) { - throw new Error("Invalid number of nodes"); + throw new Error("Invalid number of nodes"); + } + + var g = createGraph(), + i; + + for (i = 0; i < n - 1; ++i) { + g.addLink(i, i + 1); + // first row + g.addLink(n + i, n + i + 1); + // second row + g.addLink(i, n + i); + // ladder's step } - var g = ladder(n); + g.addLink(n - 1, 2 * n - 1); + // last step in the ladder; - g.addLink(0, n - 1); - g.addLink(n, 2 * n - 1); return g; -} + } -function complete(n) { -/** - * Complete graph Kn. - * - * @param {Number} n represents number of nodes in the complete graph. - */ - if (!n || n < 1) { - throw new Error("At least two nodes are expected for complete graph"); + function circularLadder(n) { + /** + * Circular ladder with n steps. + * + * @param {Number} n of steps in the ladder. + */ + if (!n || n < 0) { + throw new Error("Invalid number of nodes"); + } + + var g = ladder(n); + + g.addLink(0, n - 1); + g.addLink(n, 2 * n - 1); + return g; } - var g = createGraph(), - i, - j; + function complete(n) { + /** + * Complete graph Kn. + * + * @param {Number} n represents number of nodes in the complete graph. + */ + if (!n || n < 1) { + throw new Error("At least two nodes are expected for complete graph"); + } - for (i = 0; i < n; ++i) { - for (j = i + 1; j < n; ++j) { - if (i !== j) { - g.addLink(i, j); + var g = createGraph(), + i, + j; + + for (i = 0; i < n; ++i) { + for (j = i + 1; j < n; ++j) { + if (i !== j) { + g.addLink(i, j); + } } } - } - return g; -} - -function completeBipartite (n, m) { -/** - * Complete bipartite graph K n,m. Each node in the - * first partition is connected to all nodes in the second partition. - * - * @param {Number} n represents number of nodes in the first graph partition - * @param {Number} m represents number of nodes in the second graph partition - */ - if (!n || !m || n < 0 || m < 0) { - throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0"); + return g; } - var g = createGraph(), - i, j; + function completeBipartite (n, m) { + /** + * Complete bipartite graph K n,m. Each node in the + * first partition is connected to all nodes in the second partition. + * + * @param {Number} n represents number of nodes in the first graph partition + * @param {Number} m represents number of nodes in the second graph partition + */ + if (!n || !m || n < 0 || m < 0) { + throw new Error("Graph dimensions are invalid. Number of nodes in each partition should be greater than 0"); + } + + var g = createGraph(), + i, j; - for (i = 0; i < n; ++i) { - for (j = n; j < n + m; ++j) { - g.addLink(i, j); + for (i = 0; i < n; ++i) { + for (j = n; j < n + m; ++j) { + g.addLink(i, j); + } } + + return g; } - return g; -} + function path(n) { + /** + * Path graph with n steps. + * + * @param {Number} n number of nodes in the path + */ + if (!n || n < 0) { + throw new Error("Invalid number of nodes"); + } -function path(n) { -/** - * Path graph with n steps. - * - * @param {Number} n number of nodes in the path - */ - if (!n || n < 0) { - throw new Error("Invalid number of nodes"); - } + var g = createGraph(), + i; - var g = createGraph(), - i; + g.addNode(0); - g.addNode(0); + for (i = 1; i < n; ++i) { + g.addLink(i - 1, i); + } - for (i = 1; i < n; ++i) { - g.addLink(i - 1, i); + return g; } - return g; -} + function grid(n, m) { + /** + * Grid graph with n rows and m columns. + * + * @param {Number} n of rows in the graph. + * @param {Number} m of columns in the graph. + */ + if (n < 1 || m < 1) { + throw new Error("Invalid number of nodes in grid graph"); + } + var g = createGraph(), + i, + j; + if (n === 1 && m === 1) { + g.addNode(0); + return g; + } + + for (i = 0; i < n; ++i) { + for (j = 0; j < m; ++j) { + var node = i + j * n; + if (i > 0) { g.addLink(node, i - 1 + j * n); } + if (j > 0) { g.addLink(node, i + (j - 1) * n); } + } + } -function grid(n, m) { -/** - * Grid graph with n rows and m columns. - * - * @param {Number} n of rows in the graph. - * @param {Number} m of columns in the graph. - */ - if (n < 1 || m < 1) { - throw new Error("Invalid number of nodes in grid graph"); - } - var g = createGraph(), - i, - j; - if (n === 1 && m === 1) { - g.addNode(0); return g; } - for (i = 0; i < n; ++i) { - for (j = 0; j < m; ++j) { - var node = i + j * n; - if (i > 0) { g.addLink(node, i - 1 + j * n); } - if (j > 0) { g.addLink(node, i + (j - 1) * n); } + function grid3(n, m, z) { + /** + * 3D grid with n rows and m columns and z levels. + * + * @param {Number} n of rows in the graph. + * @param {Number} m of columns in the graph. + * @param {Number} z of levels in the graph. + */ + if (n < 1 || m < 1 || z < 1) { + throw new Error("Invalid number of nodes in grid3 graph"); } - } + var g = createGraph(), + i, j, k; - return g; -} + if (n === 1 && m === 1 && z === 1) { + g.addNode(0); + return g; + } -function grid3(n, m, z) { -/** - * 3D grid with n rows and m columns and z levels. - * - * @param {Number} n of rows in the graph. - * @param {Number} m of columns in the graph. - * @param {Number} z of levels in the graph. - */ - if (n < 1 || m < 1 || z < 1) { - throw new Error("Invalid number of nodes in grid3 graph"); + for (k = 0; k < z; ++k) { + for (i = 0; i < n; ++i) { + for (j = 0; j < m; ++j) { + var level = k * n * m; + var node = i + j * n + level; + if (i > 0) { g.addLink(node, i - 1 + j * n + level); } + if (j > 0) { g.addLink(node, i + (j - 1) * n + level); } + if (k > 0) { g.addLink(node, i + j * n + (k - 1) * n * m ); } + } + } + } + + return g; } - var g = createGraph(), - i, j, k; - if (n === 1 && m === 1 && z === 1) { - g.addNode(0); + function balancedBinTree(n) { + /** + * Balanced binary tree with n levels. + * + * @param {Number} n of levels in the binary tree + */ + if (n < 0) { + throw new Error("Invalid number of nodes in balanced tree"); + } + var g = createGraph(), + count = Math.pow(2, n), + level; + + if (n === 0) { + g.addNode(1); + } + + for (level = 1; level < count; ++level) { + var root = level, + left = root * 2, + right = root * 2 + 1; + + g.addLink(root, left); + g.addLink(root, right); + } + return g; } - for (k = 0; k < z; ++k) { + function noLinks(n) { + /** + * Graph with no links + * + * @param {Number} n of nodes in the graph + */ + if (n < 0) { + throw new Error("Number of nodes should be >= 0"); + } + + var g = createGraph(), i; for (i = 0; i < n; ++i) { - for (j = 0; j < m; ++j) { - var level = k * n * m; - var node = i + j * n + level; - if (i > 0) { g.addLink(node, i - 1 + j * n + level); } - if (j > 0) { g.addLink(node, i + (j - 1) * n + level); } - if (k > 0) { g.addLink(node, i + j * n + (k - 1) * n * m ); } - } + g.addNode(i); } + + return g; } - return g; -} + function cliqueCircle(cliqueCount, cliqueSize) { + /** + * A circular graph with cliques instead of individual nodes + * + * @param {Number} cliqueCount number of cliques inside circle + * @param {Number} cliqueSize number of nodes inside each clique + */ -function balancedBinTree(n) { -/** - * Balanced binary tree with n levels. - * - * @param {Number} n of levels in the binary tree - */ - if (n < 0) { - throw new Error("Invalid number of nodes in balanced tree"); - } - var g = createGraph(), - count = Math.pow(2, n), - level; + if (cliqueCount < 1) throw new Error('Invalid number of cliqueCount in cliqueCircle'); + if (cliqueSize < 1) throw new Error('Invalid number of cliqueSize in cliqueCircle'); - if (n === 0) { - g.addNode(1); - } + var graph = createGraph(); + + for (var i = 0; i < cliqueCount; ++i) { + appendClique(cliqueSize, i * cliqueSize) + + if (i > 0) { + graph.addLink(i * cliqueSize, i * cliqueSize - 1); + } + } + graph.addLink(0, graph.getNodesCount() - 1); - for (level = 1; level < count; ++level) { - var root = level, - left = root * 2, - right = root * 2 + 1; + return graph; - g.addLink(root, left); - g.addLink(root, right); + function appendClique(size, from) { + for (var i = 0; i < size; ++i) { + graph.addNode(i + from) + } + + for (var i = 0; i < size; ++i) { + for (var j = i + 1; j < size; ++j) { + graph.addLink(i + from, j + from) + } + } + } } - return g; + function wattsStrogatz(n, k, p, seed) { + /** + * Watts-Strogatz small-world graph. + * + * @param {Number} n The number of nodes + * @param {Number} k Each node is connected to k nearest neighbors in ring topology + * @param {Number} p The probability of rewiring each edge + + * @see https://github.com/networkx/networkx/blob/master/networkx/generators/random_graphs.py + */ + if (k >= n) throw new Error('Choose smaller `k`. It cannot be larger than number of nodes `n`'); + + + var random = require('ngraph.random').random(seed || 42); + + var g = createGraph(), i, to; + for (i = 0; i < n; ++i) { + g.addNode(i); + } + + // connect each node to k/2 neighbors + var neighborsSize = Math.floor(k/2 + 1); + for (var j = 1; j < neighborsSize; ++j) { + for (i = 0; i < n; ++i) { + to = (j + i) % n; + g.addLink(i, to); + } + } + + // rewire edges from each node + // loop over all nodes in order (label) and neighbors in order (distance) + // no self loops or multiple edges allowed + for (j = 1; j < neighborsSize; ++j) { + for (i = 0; i < n; ++i) { + if (random.nextDouble() < p) { + var from = i; + to = (j + i) % n; + + var newTo = random.next(n); + var needsRewire = (newTo === from || g.hasLink(from, newTo)); + if (needsRewire && g.getLinks(from).length === n - 1) { + // we cannot rewire this node, it has too many links. + continue; + } + // Enforce no self-loops or multiple edges + while (needsRewire) { + newTo = random.next(n); + needsRewire = (newTo === from || g.hasLink(from, newTo)); + } + var link = g.hasLink(from, to); + g.removeLink(link); + g.addLink(from, newTo); + } + } + } + + return g; + } } -function noLinks(n) { +},{"ngraph.graph":16,"ngraph.random":15}],15:[function(require,module,exports){ +module.exports = random; + +// TODO: Deprecate? +module.exports.random = random, +module.exports.randomIterator = randomIterator + /** - * Graph with no links - * - * @param {Number} n of nodes in the graph + * Creates seeded PRNG with two methods: + * next() and nextDouble() */ - if (n < 0) { - throw new Error("Number of nodes shoul be >= 0"); - } - - var g = createGraph(), i; - for (i = 0; i < n; ++i) { - g.addNode(i); - } +function random(inputSeed) { + var seed = typeof inputSeed === 'number' ? inputSeed : (+new Date()); + return new Generator(seed) +} - return g; +function Generator(seed) { + this.seed = seed; } -function wattsStrogatz(n, k, p, seed) { /** - * Watts-Strogatz small-world graph. - * - * @param {Number} n The number of nodes - * @param {Number} k Each node is connected to k nearest neighbors in ring topology - * @param {Number} p The probability of rewiring each edge + * Generates random integer number in the range from 0 (inclusive) to maxValue (exclusive) + * + * @param maxValue Number REQUIRED. Omitting this number will result in NaN values from PRNG. + */ +Generator.prototype.next = next; - * @see https://github.com/networkx/networkx/blob/master/networkx/generators/random_graphs.py +/** + * Generates random double number in the range from 0 (inclusive) to 1 (exclusive) + * This function is the same as Math.random() (except that it could be seeded) + */ +Generator.prototype.nextDouble = nextDouble; + +/** + * Returns a random real number uniformly in [0, 1) */ - if (k >= n) throw new Error('Choose smaller `k`. It cannot be larger than number of nodes `n`'); +Generator.prototype.uniform = nextDouble; +Generator.prototype.gaussian = gaussian; - var random = require('ngraph.random').random(seed || 42); +function gaussian() { + // use the polar form of the Box-Muller transform + // based on https://introcs.cs.princeton.edu/java/23recursion/StdRandom.java + var r, x, y; + do { + x = this.nextDouble() * 2 - 1; + y = this.nextDouble() * 2 - 1; + r = x * x + y * y; + } while (r >= 1 || r === 0); + + return x * Math.sqrt(-2 * Math.log(r)/r); +} + +function nextDouble() { + var seed = this.seed; + // Robert Jenkins' 32 bit integer hash function. + seed = ((seed + 0x7ed55d16) + (seed << 12)) & 0xffffffff; + seed = ((seed ^ 0xc761c23c) ^ (seed >>> 19)) & 0xffffffff; + seed = ((seed + 0x165667b1) + (seed << 5)) & 0xffffffff; + seed = ((seed + 0xd3a2646c) ^ (seed << 9)) & 0xffffffff; + seed = ((seed + 0xfd7046c5) + (seed << 3)) & 0xffffffff; + seed = ((seed ^ 0xb55a4f09) ^ (seed >>> 16)) & 0xffffffff; + this.seed = seed; + return (seed & 0xfffffff) / 0x10000000; +} + +function next(maxValue) { + return Math.floor(this.nextDouble() * maxValue); +} - var g = createGraph(), i, to; - for (i = 0; i < n; ++i) { - g.addNode(i); +/* + * Creates iterator over array, which returns items of array in random order + * Time complexity is guaranteed to be O(n); + */ +function randomIterator(array, customRandom) { + var localRandom = customRandom || random(); + if (typeof localRandom.next !== 'function') { + throw new Error('customRandom does not match expected API: next() function is missing'); } - // connect each node to k/2 neighbors - var neighborsSize = Math.floor(k/2 + 1); - for (var j = 1; j < neighborsSize; ++j) { - for (i = 0; i < n; ++i) { - to = (j + i) % n; - g.addLink(i, to); + return { + forEach: forEach, + + /** + * Shuffles array randomly, in place. + */ + shuffle: shuffle + }; + + function shuffle() { + var i, j, t; + for (i = array.length - 1; i > 0; --i) { + j = localRandom.next(i + 1); // i inclusive + t = array[j]; + array[j] = array[i]; + array[i] = t; } + + return array; } - // rewire edges from each node - // loop over all nodes in order (label) and neighbors in order (distance) - // no self loops or multiple edges allowed - for (j = 1; j < neighborsSize; ++j) { - for (i = 0; i < n; ++i) { - if (random.nextDouble() < p) { - var from = i; - to = (j + i) % n; + function forEach(callback) { + var i, j, t; + for (i = array.length - 1; i > 0; --i) { + j = localRandom.next(i + 1); // i inclusive + t = array[j]; + array[j] = array[i]; + array[i] = t; - var newTo = random.next(n); - var needsRewire = (newTo === from || g.hasLink(from, newTo)); - if (needsRewire && g.getLinks(from).length === n - 1) { - // we cannot rewire this node, it has too many links. - continue; - } - // Enforce no self-loops or multiple edges - while (needsRewire) { - newTo = random.next(n); - needsRewire = (newTo === from || g.hasLink(from, newTo)); - } - var link = g.hasLink(from, to); - g.removeLink(link); - g.addLink(from, newTo); - } + callback(t); } - } - return g; + if (array.length) { + callback(array[0]); + } + } } - -},{"ngraph.graph":12,"ngraph.random":26}],12:[function(require,module,exports){ +},{}],16:[function(require,module,exports){ /** * @fileOverview Contains definition of the core graph object. */ +// TODO: need to change storage layer: +// 1. Be able to get all nodes O(1) +// 2. Be able to get number of links O(1) + /** * @example * var graph = require('ngraph.graph')(); @@ -1314,13 +1635,23 @@ function createGraph(options) { // array is used to speed up all links enumeration. This is inefficient // in terms of memory, but simplifies coding. options = options || {}; - if (options.uniqueLinkId === undefined) { - // Request each link id to be unique between same nodes. This negatively - // impacts `addLink()` performance (O(n), where n - number of edges of each - // vertex), but makes operations with multigraphs more accessible. - options.uniqueLinkId = true; + if ('uniqueLinkId' in options) { + console.warn( + 'ngraph.graph: Starting from version 0.14 `uniqueLinkId` is deprecated.\n' + + 'Use `multigraph` option instead\n', + '\n', + 'Note: there is also change in default behavior: From now own each graph\n'+ + 'is considered to be not a multigraph by default (each edge is unique).' + ); + + options.multigraph = options.uniqueLinkId; } + // Dear reader, the non-multigraphs do not guarantee that there is only + // one link for a given pair of node. When this option is set to false + // we can save some memory and CPU (18% faster for non-multigraph); + if (options.multigraph === undefined) options.multigraph = false; + var nodes = typeof Object.create === 'function' ? Object.create(null) : {}, links = [], // Hash of multi-edges. Used to track ids of edges between same nodes @@ -1329,7 +1660,7 @@ function createGraph(options) { suspendEvents = 0, forEachNode = createNodeIterator(), - createLink = options.uniqueLinkId ? createUniqueLink : createSingleLink, + createLink = options.multigraph ? createUniqueLink : createSingleLink, // Our graph API provides means to listen to graph changes. Users can subscribe // to be notified about changes in the graph by using `on` method. However @@ -1355,8 +1686,6 @@ function createGraph(options) { * its data is extended with whatever comes in 'data' argument. * * @param nodeId the node's identifier. A string or number is preferred. - * note: If you request options.uniqueLinkId, then node id should not - * contain '👉 '. This will break link identifiers * @param [data] additional data for the node being added. If node already * exists its data object is augmented with the new one. * @@ -1410,14 +1739,14 @@ function createGraph(options) { * * @return number of nodes in the graph. */ - getNodesCount: function() { + getNodesCount: function () { return nodesCount; }, /** * Gets total number of links in the graph. */ - getLinksCount: function() { + getLinksCount: function () { return links.length; }, @@ -1489,6 +1818,16 @@ function createGraph(options) { */ hasLink: getLink, + /** + * Detects whether there is a node with given id + * + * Operation complexity is O(1) + * NOTE: this function is synonim for getNode() + * + * @returns node if there is one; Falsy value otherwise. + */ + hasNode: getNode, + /** * Gets an edge between two nodes. * Operation complexity is O(n) where n - number of links of a node. @@ -1552,16 +1891,14 @@ function createGraph(options) { var node = getNode(nodeId); if (!node) { - // TODO: Should I check for 👉 here? - node = new Node(nodeId); + node = new Node(nodeId, data); nodesCount++; recordNodeChange(node, 'add'); } else { + node.data = data; recordNodeChange(node, 'update'); } - node.data = data; - nodes[nodeId] = node; exitModification(); @@ -1580,9 +1917,12 @@ function createGraph(options) { enterModification(); - while (node.links.length) { - var link = node.links[0]; - removeLink(link); + var prevLinks = node.links; + if (prevLinks) { + node.links = null; + for(var i = 0; i < prevLinks.length; ++i) { + removeLink(prevLinks[i]); + } } delete nodes[nodeId]; @@ -1607,10 +1947,10 @@ function createGraph(options) { links.push(link); // TODO: this is not cool. On large graphs potentially would consume more memory. - fromNode.links.push(link); + addLinkToNode(fromNode, link); if (fromId !== toId) { // make sure we are not duplicating links for self-loops - toNode.links.push(link); + addLinkToNode(toNode, link); } recordLinkChange(link, 'add'); @@ -1621,18 +1961,20 @@ function createGraph(options) { } function createSingleLink(fromId, toId, data) { - var linkId = fromId.toString() + toId.toString(); + var linkId = makeLinkId(fromId, toId); return new Link(fromId, toId, data, linkId); } function createUniqueLink(fromId, toId, data) { - var linkId = fromId.toString() + '👉 ' + toId.toString(); + // TODO: Get rid of this method. + var linkId = makeLinkId(fromId, toId); var isMultiEdge = multiEdges.hasOwnProperty(linkId); if (isMultiEdge || getLink(fromId, toId)) { if (!isMultiEdge) { multiEdges[linkId] = 0; } - linkId += '@' + (++multiEdges[linkId]); + var suffix = '@' + (++multiEdges[linkId]); + linkId = makeLinkId(fromId + suffix, toId + suffix); } return new Link(fromId, toId, data, linkId); @@ -1684,7 +2026,7 @@ function createGraph(options) { // TODO: Use sorted links to speed this up var node = getNode(fromNodeId), i; - if (!node) { + if (!node || !node.links) { return null; } @@ -1806,6 +2148,8 @@ function createGraph(options) { // need this for old browsers. Should this be a separate module? function indexOfElementInArray(element, array) { + if (!array) return -1; + if (array.indexOf) { return array.indexOf(element); } @@ -1825,12 +2169,19 @@ function indexOfElementInArray(element, array) { /** * Internal structure to represent node; */ -function Node(id) { +function Node(id, data) { this.id = id; - this.links = []; - this.data = null; + this.links = null; + this.data = data; } +function addLinkToNode(node, link) { + if (node.links) { + node.links.push(link); + } else { + node.links = [link]; + } +} /** * Internal structure to represent links; @@ -1842,7 +2193,22 @@ function Link(fromId, toId, data, id) { this.id = id; } -},{"ngraph.events":7}],13:[function(require,module,exports){ +function hashCode(str) { + var hash = 0, i, chr, len; + if (str.length == 0) return hash; + for (i = 0, len = str.length; i < len; i++) { + chr = str.charCodeAt(i); + hash = ((hash << 5) - hash) + chr; + hash |= 0; // Convert to 32bit integer + } + return hash; +} + +function makeLinkId(fromId, toId) { + return fromId.toString() + '👉 ' + toId.toString(); +} + +},{"ngraph.events":9}],17:[function(require,module,exports){ module.exports = merge; /** @@ -1875,7 +2241,7 @@ function merge(target, options) { return target; } -},{}],14:[function(require,module,exports){ +},{}],18:[function(require,module,exports){ module.exports = { Body: Body, Vector2d: Vector2d, @@ -1942,7 +2308,7 @@ Vector3d.prototype.reset = function () { this.x = this.y = this.z = 0; }; -},{}],15:[function(require,module,exports){ +},{}],19:[function(require,module,exports){ /** * Manages a simulation of physical forces acting on bodies and springs. */ @@ -2006,6 +2372,7 @@ function physicsSimulator(settings) { springForce = createSpringForce(settings), dragForce = createDragForce(settings); + var bboxNeedsUpdate = true; var totalMovement = 0; // how much movement we made on last step var publicApi = { @@ -2152,9 +2519,17 @@ function physicsSimulator(settings) { * Returns bounding box which covers all bodies */ getBBox: function () { + if (bboxNeedsUpdate) { + bounds.update(); + bboxNeedsUpdate = false; + } return bounds.box; }, + invalidateBBox: function () { + bboxNeedsUpdate = true; + }, + gravity: function (value) { if (value !== undefined) { settings.gravity = value; @@ -2211,7 +2586,7 @@ function physicsSimulator(settings) { } }; -},{"./lib/bounds":16,"./lib/createBody":17,"./lib/dragForce":18,"./lib/eulerIntegrator":19,"./lib/spring":20,"./lib/springForce":21,"ngraph.events":7,"ngraph.expose":8,"ngraph.merge":13,"ngraph.quadtreebh":22}],16:[function(require,module,exports){ +},{"./lib/bounds":20,"./lib/createBody":21,"./lib/dragForce":22,"./lib/eulerIntegrator":23,"./lib/spring":24,"./lib/springForce":25,"ngraph.events":9,"ngraph.expose":10,"ngraph.merge":17,"ngraph.quadtreebh":26}],20:[function(require,module,exports){ module.exports = function (bodies, settings) { var random = require('ngraph.random').random(42); var boundingBox = { x1: 0, y1: 0, x2: 0, y2: 0 }; @@ -2293,14 +2668,14 @@ module.exports = function (bodies, settings) { } } -},{"ngraph.random":26}],17:[function(require,module,exports){ +},{"ngraph.random":30}],21:[function(require,module,exports){ var physics = require('ngraph.physics.primitives'); module.exports = function(pos) { return new physics.Body(pos); } -},{"ngraph.physics.primitives":14}],18:[function(require,module,exports){ +},{"ngraph.physics.primitives":18}],22:[function(require,module,exports){ /** * Represents drag force, which reduces force value on each step by given * coefficient. @@ -2329,7 +2704,7 @@ module.exports = function (options) { return api; }; -},{"ngraph.expose":8,"ngraph.merge":13}],19:[function(require,module,exports){ +},{"ngraph.expose":10,"ngraph.merge":17}],23:[function(require,module,exports){ /** * Performs forces integration, using given timestep. Uses Euler method to solve * differential equation (http://en.wikipedia.org/wiki/Euler_method ). @@ -2376,7 +2751,7 @@ function integrate(bodies, timeStep) { return (tx * tx + ty * ty)/max; } -},{}],20:[function(require,module,exports){ +},{}],24:[function(require,module,exports){ module.exports = Spring; /** @@ -2392,7 +2767,7 @@ function Spring(fromBody, toBody, length, coeff, weight) { this.weight = typeof weight === 'number' ? weight : 1; }; -},{}],21:[function(require,module,exports){ +},{}],25:[function(require,module,exports){ /** * Represents spring force, which updates forces acting on two bodies, conntected * by a spring. @@ -2444,7 +2819,7 @@ module.exports = function (options) { return api; } -},{"ngraph.expose":8,"ngraph.merge":13,"ngraph.random":26}],22:[function(require,module,exports){ +},{"ngraph.expose":10,"ngraph.merge":17,"ngraph.random":30}],26:[function(require,module,exports){ /** * This is Barnes Hut simulation algorithm for 2d case. Implementation * is highly optimized (avoids recusion and gc pressure) @@ -2773,7 +3148,7 @@ function setChild(node, idx, child) { else if (idx === 3) node.quad3 = child; } -},{"./insertStack":23,"./isSamePosition":24,"./node":25,"ngraph.random":26}],23:[function(require,module,exports){ +},{"./insertStack":27,"./isSamePosition":28,"./node":29,"ngraph.random":30}],27:[function(require,module,exports){ module.exports = InsertStack; /** @@ -2817,7 +3192,7 @@ function InsertStackElement(node, body) { this.body = body; // physical body which needs to be inserted to node } -},{}],24:[function(require,module,exports){ +},{}],28:[function(require,module,exports){ module.exports = function isSamePosition(point1, point2) { var dx = Math.abs(point1.x - point2.x); var dy = Math.abs(point1.y - point2.y); @@ -2825,7 +3200,7 @@ module.exports = function isSamePosition(point1, point2) { return (dx < 1e-8 && dy < 1e-8); }; -},{}],25:[function(require,module,exports){ +},{}],29:[function(require,module,exports){ /** * Internal data structure to represent 2D QuadTree node */ @@ -2857,7 +3232,7 @@ module.exports = function Node() { this.right = 0; }; -},{}],26:[function(require,module,exports){ +},{}],30:[function(require,module,exports){ module.exports = { random: random, randomIterator: randomIterator @@ -2944,7 +3319,7 @@ function randomIterator(array, customRandom) { }; } -},{}],27:[function(require,module,exports){ +},{}],31:[function(require,module,exports){ module.exports = save; function save(graph, customNodeTransform, customLinkTransform) { @@ -3000,7 +3375,7 @@ function save(graph, customNodeTransform, customLinkTransform) { } } -},{}],28:[function(require,module,exports){ +},{}],32:[function(require,module,exports){ module.exports = svg; svg.compile = require('./lib/compile'); @@ -3113,7 +3488,7 @@ function augment(element) { } } -},{"./lib/compile":29,"./lib/compile_template":30,"add-event-listener":2}],29:[function(require,module,exports){ +},{"./lib/compile":33,"./lib/compile_template":34,"add-event-listener":2}],33:[function(require,module,exports){ var parser = require('./domparser.js'); var svg = require('../'); @@ -3141,7 +3516,7 @@ function addNamespaces(text) { } } -},{"../":28,"./domparser.js":31}],30:[function(require,module,exports){ +},{"../":32,"./domparser.js":35}],34:[function(require,module,exports){ module.exports = template; var BINDING_EXPR = /{{(.+?)}}/; @@ -3235,7 +3610,7 @@ function bindTextContent(element, allBindings) { } } -},{}],31:[function(require,module,exports){ +},{}],35:[function(require,module,exports){ module.exports = createDomparser(); function createDomparser() { @@ -3251,7 +3626,7 @@ function fail() { throw new Error('DOMParser is not supported by this platform. Please open issue here https://github.com/anvaka/simplesvg'); } -},{}],32:[function(require,module,exports){ +},{}],36:[function(require,module,exports){ var centrality = require('ngraph.centrality'); module.exports = centralityWrapper; @@ -3289,7 +3664,7 @@ function toVivaGraphCentralityFormat(centrality) { } } -},{"ngraph.centrality":4}],33:[function(require,module,exports){ +},{"ngraph.centrality":4}],37:[function(require,module,exports){ /** * @fileOverview Contains collection of primitive operations under graph. * @@ -3324,7 +3699,7 @@ function operations() { }; }; -},{}],34:[function(require,module,exports){ +},{}],38:[function(require,module,exports){ /** * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ @@ -3373,7 +3748,7 @@ function domInputManager(graph, graphics) { } } -},{"./dragndrop.js":35}],35:[function(require,module,exports){ +},{"./dragndrop.js":39}],39:[function(require,module,exports){ /** * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ @@ -3656,7 +4031,7 @@ function dragndrop(element) { }; } -},{"../Utils/browserInfo.js":39,"../Utils/documentEvents.js":40,"../Utils/findElementPosition.js":41}],36:[function(require,module,exports){ +},{"../Utils/browserInfo.js":43,"../Utils/documentEvents.js":44,"../Utils/findElementPosition.js":45}],40:[function(require,module,exports){ /** * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka */ @@ -3727,7 +4102,7 @@ function webglInputManager(graph, graphics) { }; } -},{"../WebGL/webglInputEvents.js":57}],37:[function(require,module,exports){ +},{"../WebGL/webglInputEvents.js":61}],41:[function(require,module,exports){ module.exports = constant; var merge = require('ngraph.merge'); @@ -3926,7 +4301,7 @@ function constant(graph, userSettings) { } } -},{"../Utils/rect.js":45,"ngraph.merge":13,"ngraph.random":26}],38:[function(require,module,exports){ +},{"../Utils/rect.js":49,"ngraph.merge":17,"ngraph.random":30}],42:[function(require,module,exports){ /** * This module provides compatibility layer with 0.6.x library. It will be * removed in the next version @@ -3971,7 +4346,7 @@ function backwardCompatibleEvents(g) { } } -},{"ngraph.events":7}],39:[function(require,module,exports){ +},{"ngraph.events":9}],43:[function(require,module,exports){ module.exports = browserInfo(); function browserInfo() { @@ -4000,7 +4375,7 @@ function browserInfo() { }; } -},{}],40:[function(require,module,exports){ +},{}],44:[function(require,module,exports){ var nullEvents = require('./nullEvents.js'); module.exports = createDocumentEvents(); @@ -4024,7 +4399,7 @@ function off(eventName, handler) { document.removeEventListener(eventName, handler); } -},{"./nullEvents.js":44}],41:[function(require,module,exports){ +},{"./nullEvents.js":48}],45:[function(require,module,exports){ /** * Finds the absolute position of an element on a page */ @@ -4043,7 +4418,7 @@ function findElementPosition(obj) { return [curleft, curtop]; } -},{}],42:[function(require,module,exports){ +},{}],46:[function(require,module,exports){ module.exports = getDimension; function getDimension(container) { @@ -4065,7 +4440,7 @@ function getDimension(container) { }; } -},{}],43:[function(require,module,exports){ +},{}],47:[function(require,module,exports){ var intersect = require('gintersect'); module.exports = intersectRect; @@ -4077,7 +4452,7 @@ function intersectRect(left, top, right, bottom, x1, y1, x2, y2) { intersect(right, top, left, top, x1, y1, x2, y2); } -},{"gintersect":3}],44:[function(require,module,exports){ +},{"gintersect":3}],48:[function(require,module,exports){ module.exports = createNullEvents(); function createNullEvents() { @@ -4090,7 +4465,7 @@ function createNullEvents() { function noop() { } -},{}],45:[function(require,module,exports){ +},{}],49:[function(require,module,exports){ module.exports = Rect; /** @@ -4103,7 +4478,7 @@ function Rect (x1, y1, x2, y2) { this.y2 = y2 || 0; } -},{}],46:[function(require,module,exports){ +},{}],50:[function(require,module,exports){ (function (global){ /** * @author Andrei Kashcha (aka anvaka) / https://github.com/anvaka @@ -4199,7 +4574,7 @@ function createTimer() { function noop() {} }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],47:[function(require,module,exports){ +},{}],51:[function(require,module,exports){ var nullEvents = require('./nullEvents.js'); module.exports = createDocumentEvents(); @@ -4224,7 +4599,7 @@ function off(eventName, handler) { } -},{"./nullEvents.js":44}],48:[function(require,module,exports){ +},{"./nullEvents.js":48}],52:[function(require,module,exports){ /** * @fileOverview Defines a graph renderer that uses CSS based drawings. * @@ -4265,7 +4640,7 @@ var dragndrop = require('../Input/dragndrop.js'); * * // Layout algorithm to be used. The algorithm is expected to comply with defined * // interface and is expected to be iterative. Renderer will use it then to calculate - * // grpaph's layout. For examples of the interface refer to Viva.Graph.Layout.forceDirected() + * // graph's layout. For examples of the interface refer to Viva.Graph.Layout.forceDirected() * layout : Viva.Graph.Layout.forceDirected(), * * // Directs renderer to display links. Usually rendering links is the slowest part of this @@ -4385,6 +4760,10 @@ function renderer(graph, settings) { getGraphics: function() { return graphics; }, + + getLayout: function() { + return layout; + }, /** * Removes this renderer and deallocates all resources/timers @@ -4711,7 +5090,7 @@ function renderer(graph, settings) { } } -},{"../Input/domInputManager.js":34,"../Input/dragndrop.js":35,"../Utils/getDimensions.js":42,"../Utils/timer.js":46,"../Utils/windowEvents.js":47,"./svgGraphics.js":49,"ngraph.events":7,"ngraph.forcelayout":9}],49:[function(require,module,exports){ +},{"../Input/domInputManager.js":38,"../Input/dragndrop.js":39,"../Utils/getDimensions.js":46,"../Utils/timer.js":50,"../Utils/windowEvents.js":51,"./svgGraphics.js":53,"ngraph.events":9,"ngraph.forcelayout":11}],53:[function(require,module,exports){ /** * @fileOverview Defines a graph renderer that uses SVG based drawings. * @@ -5069,7 +5448,7 @@ function svgGraphics() { } } -},{"../Input/domInputManager.js":34,"ngraph.events":7,"simplesvg":28}],50:[function(require,module,exports){ +},{"../Input/domInputManager.js":38,"ngraph.events":9,"simplesvg":32}],54:[function(require,module,exports){ /** * @fileOverview Defines a graph renderer that uses WebGL based drawings. * @@ -5657,7 +6036,7 @@ function webglGraphics(options) { return graphics; } -},{"../Input/webglInputManager.js":36,"../WebGL/webglLine.js":58,"../WebGL/webglLinkProgram.js":59,"../WebGL/webglNodeProgram.js":60,"../WebGL/webglSquare.js":61,"ngraph.events":7,"ngraph.merge":13}],51:[function(require,module,exports){ +},{"../Input/webglInputManager.js":40,"../WebGL/webglLine.js":62,"../WebGL/webglLinkProgram.js":63,"../WebGL/webglNodeProgram.js":64,"../WebGL/webglSquare.js":65,"ngraph.events":9,"ngraph.merge":17}],55:[function(require,module,exports){ module.exports = parseColor; function parseColor(color) { @@ -5681,7 +6060,7 @@ function parseColor(color) { return parsedColor; } -},{}],52:[function(require,module,exports){ +},{}],56:[function(require,module,exports){ module.exports = Texture; /** @@ -5694,7 +6073,7 @@ function Texture(size) { this.canvas.width = this.canvas.height = size; } -},{}],53:[function(require,module,exports){ +},{}],57:[function(require,module,exports){ /** * @fileOverview Utility functions for webgl rendering. * @@ -5801,7 +6180,7 @@ function swapArrayPart(array, from, to, elementsCount) { } } -},{}],54:[function(require,module,exports){ +},{}],58:[function(require,module,exports){ var Texture = require('./texture.js'); module.exports = webglAtlas; @@ -6005,7 +6384,7 @@ function isPowerOf2(n) { return (n & (n - 1)) === 0; } -},{"./texture.js":52}],55:[function(require,module,exports){ +},{"./texture.js":56}],59:[function(require,module,exports){ module.exports = webglImage; /** @@ -6037,7 +6416,7 @@ function webglImage(size, src) { }; } -},{}],56:[function(require,module,exports){ +},{}],60:[function(require,module,exports){ /** * @fileOverview Defines an image nodes for webglGraphics class. * Shape of nodes is square. @@ -6301,7 +6680,7 @@ function createNodeVertexShader() { ].join("\n"); } -},{"./webgl.js":53,"./webglAtlas.js":54}],57:[function(require,module,exports){ +},{"./webgl.js":57,"./webglAtlas.js":58}],61:[function(require,module,exports){ var documentEvents = require('../Utils/documentEvents.js'); module.exports = webglInputEvents; @@ -6561,7 +6940,7 @@ function webglInputEvents(webglGraphics) { } } -},{"../Utils/documentEvents.js":40}],58:[function(require,module,exports){ +},{"../Utils/documentEvents.js":44}],62:[function(require,module,exports){ var parseColor = require('./parseColor.js'); module.exports = webglLine; @@ -6582,7 +6961,7 @@ function webglLine(color) { }; } -},{"./parseColor.js":51}],59:[function(require,module,exports){ +},{"./parseColor.js":55}],63:[function(require,module,exports){ /** * @fileOverview Defines a naive form of links for webglGraphics class. * This form allows to change color of links. @@ -6740,7 +7119,7 @@ function webglLinkProgram() { }; } -},{"./webgl.js":53}],60:[function(require,module,exports){ +},{"./webgl.js":57}],64:[function(require,module,exports){ /** * @fileOverview Defines a naive form of nodes for webglGraphics class. * This form allows to change color of node. Shape of nodes is rectangular. @@ -6905,7 +7284,7 @@ function webglNodeProgram() { } } -},{"./webgl.js":53}],61:[function(require,module,exports){ +},{"./webgl.js":57}],65:[function(require,module,exports){ var parseColor = require('./parseColor.js'); module.exports = webglSquare; @@ -6931,7 +7310,7 @@ function webglSquare(size, color) { }; } -},{"./parseColor.js":51}],62:[function(require,module,exports){ +},{"./parseColor.js":55}],66:[function(require,module,exports){ // todo: this should be generated at build time. module.exports = '0.8.1'; diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 3e2be0b..84f31bb 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,2 +1,3 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,g=f*t+d*r+p,0!==v&&0!==g&&v>=0==g>=0?null:(y=s*d-f*c,0===y?null:(x=y<0?-y/2:y/2,x=0,w=c*p-d*l,b.x=(w<0?w-x:w+x)/y,w=f*l-s*p,b.y=(w<0?w-x:w+x)/y,b)))}n.exports=r},{}],4:[function(e,n,t){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js")},{"./src/betweenness.js":5,"./src/degree.js":6}],5:[function(e,n,t){function r(e,n){function t(e){g[e]/=2}function r(e){g[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;i0&&o.addLink(i,t-1+r*e),r>0&&o.addLink(i,t+(r-1)*e)}return o}function f(e,n,t){if(e<1||n<1||t<1)throw new Error("Invalid number of nodes in grid3 graph");var r,o,i,a=p();if(1===e&&1===n&&1===t)return a.addNode(0),a;for(i=0;i0&&a.addLink(s,r-1+o*e+u),o>0&&a.addLink(s,r+(o-1)*e+u),i>0&&a.addLink(s,r+o*e+(i-1)*e*n)}return a}function c(e){if(e<0)throw new Error("Invalid number of nodes in balanced tree");var n,t=p(),r=Math.pow(2,e);for(0===e&&t.addNode(1),n=1;n= 0");var n,t=p();for(n=0;n=n)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var i,a,u=e("ngraph.random").random(o||42),s=p();for(i=0;i=0&&t.links.splice(n,1)),r&&(n=o(e,r.links),n>=0&&r.links.splice(n,1)),U(e,"remove"),F(),!0}function h(e,n){var t,r=f(e);if(!r)return null;for(t=0;t0&&(O.fire("changed",M),M.length=0)}function P(){return Object.keys?k:j}function k(e){if("function"==typeof e)for(var n=Object.keys(A),t=0;t=0?i:-1,o);return v.push(a),a},getTotalMovement:function(){return x},removeSpring:function(e){if(e){var n=v.indexOf(e);return n>-1?(v.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return h.getBestNewPosition(e)},getBBox:function(){return h.box},gravity:function(e){return void 0!==e?(n.gravity=e,g.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,g.options({theta:e}),this):n.theta}};return o(n,w),a(w),w}n.exports=r},{"./lib/bounds":16,"./lib/createBody":17,"./lib/dragForce":18,"./lib/eulerIntegrator":19,"./lib/spring":20,"./lib/springForce":21,"ngraph.events":7,"ngraph.expose":8,"ngraph.merge":13,"ngraph.quadtreebh":22}],16:[function(e,n,t){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;u1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/u}n.exports=r},{}],20:[function(e,n,t){function r(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=r},{}],21:[function(e,n,t){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":8,"ngraph.merge":13,"ngraph.random":26}],22:[function(e,n,t){function r(e,n){return 0===n?e.quad0:1===n?e.quad1:2===n?e.quad2:3===n?e.quad3:null}function o(e,n,t){0===n?e.quad0=t:1===n?e.quad1=t:2===n?e.quad2=t:3===n&&(e.quad3=t)}n.exports=function(n){function t(){var e=h[m];return e?(e.quad0=null,e.quad1=null,e.quad2=null,e.quad3=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0):(e=new f,h[m]=e),++m,e}function i(e){var n,t,r,o,i=p,a=0,u=0,f=1,c=0,d=1;for(i[0]=y;f;){var v=i[c],h=v.body;f-=1,c+=1;var m=h!==e;h&&m?(t=h.pos.x-e.pos.x,r=h.pos.y-e.pos.y,o=Math.sqrt(t*t+r*r),0===o&&(t=(s.nextDouble()-.5)/50,r=(s.nextDouble()-.5)/50,o=Math.sqrt(t*t+r*r)),n=l*h.mass*e.mass/(o*o*o),a+=n*t,u+=n*r):m&&(t=v.massX/v.mass-e.pos.x,r=v.massY/v.mass-e.pos.y,o=Math.sqrt(t*t+r*r),0===o&&(t=(s.nextDouble()-.5)/50,r=(s.nextDouble()-.5)/50,o=Math.sqrt(t*t+r*r)),(v.right-v.left)/oi&&(i=f),ca&&(a=c)}var d=i-r,l=a-o;for(d>l?a=o+d:i=r+l,m=0,y=t(),y.left=r,y.right=i,y.top=o,y.bottom=a,n=s-1,n>=0&&(y.body=e[n]);n--;)u(e[n],y)}function u(e){for(v.reset(),v.push(y,e);!v.isEmpty();){var n=v.pop(),i=n.node,a=n.body;if(i.body){var u=i.body;if(i.body=null,d(u.pos,a.pos)){var f=3;do{var c=s.nextDouble(),l=(i.right-i.left)*c,p=(i.bottom-i.top)*c;u.pos.x=i.left+l,u.pos.y=i.top+p,f-=1}while(f>0&&d(u.pos,a.pos));if(0===f&&d(u.pos,a.pos))return}v.push(i,u),v.push(i,a)}else{var g=a.pos.x,h=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*g,i.massY=i.massY+a.mass*h;var m=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;g>w&&(m+=1,x=w,w=i.right),h>E&&(m+=2,b=E,E=i.bottom);var L=r(i,m);L?v.push(L,a):(L=t(),L.left=x,L.top=b,L.right=w,L.bottom=E,L.body=a,o(i,m,L))}}}n=n||{},n.gravity="number"==typeof n.gravity?n.gravity:-1,n.theta="number"==typeof n.theta?n.theta:.8;var s=e("ngraph.random").random(1984),f=e("./node"),c=e("./insertStack"),d=e("./isSamePosition"),l=n.gravity,p=[],v=new c,g=n.theta,h=[],m=0,y=t();return{insertBodies:a,getRoot:function(){return y},updateBodyForce:i,options:function(e){return e?("number"==typeof e.gravity&&(l=e.gravity),"number"==typeof e.theta&&(g=e.theta),this):{gravity:l,theta:g}}}}},{"./insertStack":23,"./isSamePosition":24,"./node":25,"ngraph.random":26}],23:[function(e,n,t){function r(){this.stack=[],this.popIdx=0}function o(e,n){this.node=e,this.body=n}n.exports=r,r.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new o(e,n),++this.popIdx},pop:function(){if(this.popIdx>0)return this.stack[--this.popIdx]},reset:function(){this.popIdx=0}}},{}],24:[function(e,n,t){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return t<1e-8&&r<1e-8}},{}],25:[function(e,n,t){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],26:[function(e,n,t){function r(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function o(e,n){var t=n||r();if("function"!=typeof t.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var r,o,i;for(r=e.length-1;r>0;--r)o=t.next(r+1),i=e[o],e[o]=e[r],e[r]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,r,o;for(n=e.length-1;n>0;--n)r=t.next(n+1),o=e[r],e[r]=e[n],e[n]=o;return e}}}n.exports={random:r,randomIterator:o}},{}],27:[function(e,n,t){function r(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=r},{}],28:[function(e,n,t){function r(e,n){var t=o(e);if(void 0===n)return t;for(var r=Object.keys(n),i=0;iv&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},j=function(e){p=!1,o.off("touchmove",k),o.off("touchend",j),o.off("touchcancel",j),c=null,r&&r(e)},A=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,o.on("touchmove",k),o.on("touchend",j),o.on("touchcancel",j))},_=function(e){return 1===e.touches.length?A(e,e.touches[0]):void(2===e.touches.length&&(m(e), -y(e),v=P(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),o.off("mousemove",w),o.off("mouseup",E),o.off("touchmove",k),o.off("touchend",j),o.off("touchcancel",j),N(null)}}}n.exports=r;var o=e("../Utils/documentEvents.js"),i=e("../Utils/browserInfo.js"),a=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":39,"../Utils/documentEvents.js":40,"../Utils/findElementPosition.js":41}],36:[function(e,n,t){function r(e,n){var t=o(n),r=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){r=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(r);var o=i[e.id];return o&&o.onStart&&o.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(r),r=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(r){var t=i[r.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=r;var o=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":57}],37:[function(e,n,t){function r(e,n){function t(e){return d[e]}n=o(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var r=i(n.seed),u=new a(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(e){return{x:r.next(n.maxX),y:r.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},g=function(e){for(var n=0;n=0:"boolean"!=typeof z||z}function r(){G=G||window.document.body,F=F||i(e,{springLength:80,springCoeff:2e-4}),O=O||a(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(O.inputManager||s)(e,O)}function l(){O.beginRender(),n.renderLinks&&O.renderLinks(),O.renderNodes(),O.endRender()}function p(){return X=F.step()&&!V,l(),!X}function v(e){R||(R=void 0!==e?f(function(){if(e-=1,e<0){var n=!1;return n}return p()},M):f(p,M))}function g(){W||(X=!1,R.restart())}function h(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;e0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,g(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):r=e),t},getSvgRoot:function(){return t}};return i(b),b}n.exports=r;var o=e("simplesvg"),i=e("ngraph.events"),a=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":34,"ngraph.events":7,simplesvg:28}],50:[function(e,n,t){function r(e){e=c(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,r,d,l,p,v,g,h=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=i(),N=a(),P=function(e){return u()},k=function(e){return s(3014898687)},j=function(){L.updateTransform(y),N.updateTransform(y)},A=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),r&&r.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),N&&N.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){if("function"==typeof e)return P=e,this},link:function(e){if("function"==typeof e)return k=e,this},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:o,beginRender:function(){},endRender:function(){m>0&&L.render(),h>0&&N.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,j()},addLink:function(e,n){var t=m++,r=k(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=h++,r=P(e);return r.id=t,r.position=n,r.node=e,N.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],j()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,j(),I(this),y[0]},resetScale:function(){return A(),r&&(_(),j()),this},updateSize:_,init:function(o){var i={};if(e.preserveDrawingBuffer&&(i.preserveDrawingBuffer=!0),n=o,_(),A(),n.appendChild(t),r=t.getContext("experimental-webgl",i),!r){var a="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(a),a}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var u=e.clearColorValue;r.clearColor(u.r,u.g,u.b,u.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}L.load(r),L.updateSize(d/2,l/2),N.load(r),N.updateSize(d/2,l/2),j(),"function"==typeof g&&g(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(t0&&(h-=1);var n=b[e.id];delete b[e.id],N.removeNode(n);var t=n.id;if(te.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;o=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*h,r.row*h,h,h),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/g<<0,i=r%g;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*h,i=n.row*h;r.drawImage(t,e.col*h,e.row*h,h,h,o,i,h,h),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,g=Math.sqrt(e||1024)<<0,h=g,m=1,y={},x=0,w=[],b=[];if(!o(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:r,getCoordinates:a,load:u};return E}function o(e){return 0===(e&e-1)}var i=e("./texture.js");n.exports=r},{"./texture.js":52}],55:[function(e,n,t){function r(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=r},{}],56:[function(e,n,t){function r(){function e(e,n){e.nativeObject&&h.deleteTexture(e.nativeObject);var t=h.createTexture();h.activeTexture(h["TEXTURE"+n]),h.bindTexture(h.TEXTURE_2D,t),h.texImage2D(h.TEXTURE_2D,0,h.RGBA,h.RGBA,h.UNSIGNED_BYTE,e.canvas),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.LINEAR),h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.LINEAR_MIPMAP_NEAREST),h.generateMipmap(h.TEXTURE_2D),h.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(A-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*N,A*N,N))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){h.useProgram(g),h.bindBuffer(h.ARRAY_BUFFER,m),h.bufferData(h.ARRAY_BUFFER,_,h.DYNAMIC_DRAW),L&&(L=!1,h.uniformMatrix4fv(x.transform,!1,E),h.uniform2f(x.screenSize,w,b)),h.vertexAttribPointer(x.vertexPos,2,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),h.vertexAttribPointer(x.customAttributes,1,h.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),h.drawArrays(h.TRIANGLES,0,6*A)}var v,g,h,m,y,x,w,b,E,L,N=18,P=o(),k=i(),j=1024,A=0,_=new Float32Array(64);return{load:t,position:r,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function o(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function i(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var a=e("./webglAtlas.js"),u=e("./webgl.js");n.exports=r},{"./webgl.js":53,"./webglAtlas.js":54}],57:[function(e,n,t){function r(e){function n(){x=null}function t(e){x=e}function r(e){return"function"==typeof e&&k.push(e),A}function i(e){return"function"==typeof e&&P.push(e),A}function a(e){return"function"==typeof e&&N.push(e),A}function u(e){return"function"==typeof e&&L.push(e),A}function s(e){return"function"==typeof e&&E.push(e),A}function f(e){return"function"==typeof e&&b.push(e),A}function c(e){return"function"==typeof e&&w.push(e),A}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-oh.byteLength){var e=new ArrayBuffer(2*h.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,h=e}};return{load:function(a){n=a,r=o(a),e=r.createProgram(v,p),n.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),g+=1,a=e.id},removeLink:function(e){g>0&&(g-=1),e.id0&&r.copyArrayPart(y,e.id*d,g*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,h,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*g),a=g-1},bringToFront:function(e){a>e.id&&r.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],60:[function(e,n,t){function r(){function e(){if((k+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(P),N=n,P=t,L=e}}function n(e){d=e,v=o(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;N[t*x]=n.x,N[t*x+1]=-n.y,N[t*x+2]=e.size,P[t*x+3]=e.color}function r(e){y=!0,m=e}function i(e,n){g=e,h=n,y=!0}function a(e){k>0&&(k-=1),e.id0&&v.copyArrayPart(P,e.id*x,k*x,x)}function u(){e(),k+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,g,h)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,k)}var c,d,l,p,v,g,h,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),N=new Float32Array(L),P=new Uint32Array(L),k=0;return{load:n,position:t,updateTransform:r,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":53}],61:[function(e,n,t){function r(e,n){return{size:"number"==typeof e?e:10,color:o(n)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":51}],62:[function(e,n,t){n.exports="0.8.1"},{}]},{},[1])(1)}); \ No newline at end of file +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,h=f*t+d*r+p,0!==v&&0!==h&&v>=0==h>=0?null:(y=s*d-f*c,0===y?null:(x=y<0?-y/2:y/2,x=0,w=c*p-d*l,b.x=(w<0?w-x:w+x)/y,w=f*l-s*p,b.y=(w<0?w-x:w+x)/y,b)))}n.exports=r},{}],4:[function(e,n,t){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js"),n.exports.closeness=e("./src/closeness.js"),n.exports.eccentricity=e("./src/eccentricity.js")},{"./src/betweenness.js":5,"./src/closeness.js":6,"./src/degree.js":7,"./src/eccentricity.js":8}],5:[function(e,n,t){function r(e,n){function t(e){h[e]/=2}function r(e){h[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o0?f[a]=(n-1)/t:f[a]=0}function i(t){function r(e){var n=e.id;s[n]=-1}function o(e){var n=e.id;s[n]===-1&&(s[n]=s[i]+1,u.push(n))}for(e.forEachNode(r),s[t]=0,u.push(t);u.length;){var i=u.shift();e.forEachLinkedNode(i,o,n)}}var a,u=[],s=Object.create(null),f=Object.create(null);return e.forEachNode(t),e.forEachNode(r),f}n.exports=r},{}],7:[function(e,n,t){function r(e,n){function t(n){var t=e.getLinks(n.id);u[n.id]=r(t,n.id)}var r,u=Object.create(null);if(n=(n||"both").toLowerCase(),"both"===n||"inout"===n)r=a;else if("in"===n)r=o;else{if("out"!==n)throw new Error("Expected centrality degree kind is: in, out or both");r=i}return e.forEachNode(t),u}function o(e,n){var t=0;if(!e)return t;for(var r=0;r1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;i0&&i.addLink(a,r-1+o*e),o>0&&i.addLink(a,r+(o-1)*e)}return i}function s(e,t,r){if(e<1||t<1||r<1)throw new Error("Invalid number of nodes in grid3 graph");var o,i,a,u=n();if(1===e&&1===t&&1===r)return u.addNode(0),u;for(a=0;a0&&u.addLink(f,o-1+i*e+s),i>0&&u.addLink(f,o+(i-1)*e+s),a>0&&u.addLink(f,o+i*e+(a-1)*e*t)}return u}function f(e){if(e<0)throw new Error("Invalid number of nodes in balanced tree");var t,r=n(),o=Math.pow(2,e);for(0===e&&r.addNode(1),t=1;t= 0");var t,r=n();for(t=0;t0&&o.addLink(i*t,i*t-1);return o.addLink(0,o.getNodesCount()-1),o}function l(t,r,o,i){if(r>=t)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var a,u,s=e("ngraph.random").random(i||42),f=n();for(a=0;a=1||0===e);return n*Math.sqrt(-2*Math.log(e)/e)}function a(){var e=this.seed;return e=e+2127912214+(e<<12)&4294967295,e=4294967295&(3345072700^e^e>>>19),e=e+374761393+(e<<5)&4294967295,e=4294967295&(e+3550635116^e<<9),e=e+4251993797+(e<<3)&4294967295,e=4294967295&(3042594569^e^e>>>16),this.seed=e,(268435455&e)/268435456}function u(e){return Math.floor(this.nextDouble()*e)}function s(e,n){function t(){var n,t,r;for(n=e.length-1;n>0;--n)t=i.next(n+1),r=e[t],e[t]=e[n],e[n]=r;return e}function o(n){var t,r,o;for(t=e.length-1;t>0;--t)r=i.next(t+1),o=e[r],e[r]=e[t],e[t]=o,n(o);e.length&&n(e[0])}var i=n||r();if("function"!=typeof i.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:o,shuffle:t}}n.exports=r,n.exports.random=r,n.exports.randomIterator=s,o.prototype.next=u,o.prototype.nextDouble=a,o.prototype.uniform=a,o.prototype.gaussian=i},{}],16:[function(e,n,t){function r(e){function n(){function e(){return q.beginUpdate=F=k,q.endUpdate=G=P,B=t,O=r,q.on=n,n.apply(q,arguments)}var n=q.on;q.on=e}function t(e,n){R.push({link:e,changeType:n})}function r(e,n){R.push({node:e,changeType:n})}function c(e,n){if(void 0===e)throw new Error("Invalid node identifier");F();var t=d(e);return t?(t.data=n,O(t,"update")):(t=new i(e,n),S++,O(t,"add")),I[e]=t,G(),t}function d(e){return I[e]}function l(e){var n=d(e);if(!n)return!1;F();var t=n.links;if(t){n.links=null;for(var r=0;r=0&&t.links.splice(n,1)),r&&(n=o(e,r.links),n>=0&&r.links.splice(n,1)),B(e,"remove"),G(),!0}function y(e,n){var t,r=d(e);if(!r||!r.links)return null;for(t=0;t0&&(q.fire("changed",R),R.length=0)}function j(){return Object.keys?A:_}function A(e){if("function"==typeof e)for(var n=Object.keys(I),t=0;t=0?i:-1,o);return v.push(a),a},getTotalMovement:function(){return w},removeSpring:function(e){if(e){var n=v.indexOf(e);return n>-1?(v.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return x&&(g.update(),x=!1),g.box},invalidateBBox:function(){x=!0},gravity:function(e){return void 0!==e?(n.gravity=e,h.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,h.options({theta:e}),this):n.theta}};return o(n,b),a(b),b}n.exports=r},{"./lib/bounds":20,"./lib/createBody":21,"./lib/dragForce":22,"./lib/eulerIntegrator":23,"./lib/spring":24,"./lib/springForce":25,"ngraph.events":9,"ngraph.expose":10,"ngraph.merge":17,"ngraph.quadtreebh":26}],20:[function(e,n,t){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;u1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/u}n.exports=r},{}],24:[function(e,n,t){function r(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=r},{}],25:[function(e,n,t){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":10,"ngraph.merge":17,"ngraph.random":30}],26:[function(e,n,t){function r(e,n){return 0===n?e.quad0:1===n?e.quad1:2===n?e.quad2:3===n?e.quad3:null}function o(e,n,t){0===n?e.quad0=t:1===n?e.quad1=t:2===n?e.quad2=t:3===n&&(e.quad3=t)}n.exports=function(n){function t(){var e=g[m];return e?(e.quad0=null,e.quad1=null,e.quad2=null,e.quad3=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0):(e=new f,g[m]=e),++m,e}function i(e){var n,t,r,o,i=p,a=0,u=0,f=1,c=0,d=1;for(i[0]=y;f;){var v=i[c],g=v.body;f-=1,c+=1;var m=g!==e;g&&m?(t=g.pos.x-e.pos.x,r=g.pos.y-e.pos.y,o=Math.sqrt(t*t+r*r),0===o&&(t=(s.nextDouble()-.5)/50,r=(s.nextDouble()-.5)/50,o=Math.sqrt(t*t+r*r)),n=l*g.mass*e.mass/(o*o*o),a+=n*t,u+=n*r):m&&(t=v.massX/v.mass-e.pos.x,r=v.massY/v.mass-e.pos.y,o=Math.sqrt(t*t+r*r),0===o&&(t=(s.nextDouble()-.5)/50,r=(s.nextDouble()-.5)/50,o=Math.sqrt(t*t+r*r)),(v.right-v.left)/oi&&(i=f),ca&&(a=c)}var d=i-r,l=a-o;for(d>l?a=o+d:i=r+l,m=0,y=t(),y.left=r,y.right=i,y.top=o,y.bottom=a,n=s-1,n>=0&&(y.body=e[n]);n--;)u(e[n],y)}function u(e){for(v.reset(),v.push(y,e);!v.isEmpty();){var n=v.pop(),i=n.node,a=n.body;if(i.body){var u=i.body;if(i.body=null,d(u.pos,a.pos)){var f=3;do{var c=s.nextDouble(),l=(i.right-i.left)*c,p=(i.bottom-i.top)*c;u.pos.x=i.left+l,u.pos.y=i.top+p,f-=1}while(f>0&&d(u.pos,a.pos));if(0===f&&d(u.pos,a.pos))return}v.push(i,u),v.push(i,a)}else{var h=a.pos.x,g=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*h,i.massY=i.massY+a.mass*g;var m=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;h>w&&(m+=1,x=w,w=i.right),g>E&&(m+=2,b=E,E=i.bottom);var L=r(i,m);L?v.push(L,a):(L=t(),L.left=x,L.top=b,L.right=w,L.bottom=E,L.body=a,o(i,m,L))}}}n=n||{},n.gravity="number"==typeof n.gravity?n.gravity:-1,n.theta="number"==typeof n.theta?n.theta:.8;var s=e("ngraph.random").random(1984),f=e("./node"),c=e("./insertStack"),d=e("./isSamePosition"),l=n.gravity,p=[],v=new c,h=n.theta,g=[],m=0,y=t();return{insertBodies:a,getRoot:function(){return y},updateBodyForce:i,options:function(e){return e?("number"==typeof e.gravity&&(l=e.gravity),"number"==typeof e.theta&&(h=e.theta),this):{gravity:l,theta:h}}}}},{"./insertStack":27,"./isSamePosition":28,"./node":29,"ngraph.random":30}],27:[function(e,n,t){function r(){this.stack=[],this.popIdx=0}function o(e,n){this.node=e,this.body=n}n.exports=r,r.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new o(e,n),++this.popIdx},pop:function(){if(this.popIdx>0)return this.stack[--this.popIdx]},reset:function(){this.popIdx=0}}},{}],28:[function(e,n,t){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return t<1e-8&&r<1e-8}},{}],29:[function(e,n,t){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],30:[function(e,n,t){function r(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function o(e,n){var t=n||r();if("function"!=typeof t.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var r,o,i;for(r=e.length-1;r>0;--r)o=t.next(r+1),i=e[o],e[o]=e[r],e[r]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,r,o;for(n=e.length-1;n>0;--n)r=t.next(n+1),o=e[r],e[r]=e[n],e[n]=o;return e}}}n.exports={random:r,randomIterator:o}},{}],31:[function(e,n,t){function r(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=r},{}],32:[function(e,n,t){function r(e,n){var t=o(e);if(void 0===n)return t;for(var r=Object.keys(n),i=0;iv&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},j=function(e){p=!1,o.off("touchmove",P),o.off("touchend",j),o.off("touchcancel",j),c=null,r&&r(e)},A=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,o.on("touchmove",P),o.on("touchend",j),o.on("touchcancel",j))},_=function(e){return 1===e.touches.length?A(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=k(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),o.off("mousemove",w),o.off("mouseup",E),o.off("touchmove",P),o.off("touchend",j),o.off("touchcancel",j),N(null)}}}n.exports=r;var o=e("../Utils/documentEvents.js"),i=e("../Utils/browserInfo.js"),a=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":43,"../Utils/documentEvents.js":44,"../Utils/findElementPosition.js":45}],40:[function(e,n,t){function r(e,n){var t=o(n),r=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){r=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(r);var o=i[e.id];return o&&o.onStart&&o.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(r),r=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(r){var t=i[r.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=r;var o=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":61}],41:[function(e,n,t){function r(e,n){function t(e){return d[e]}n=o(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var r=i(n.seed),u=new a(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(e){return{x:r.next(n.maxX),y:r.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},h=function(e){for(var n=0;n=0:"boolean"!=typeof q||q}function r(){G=G||window.document.body,O=O||i(e,{springLength:80,springCoeff:2e-4}),F=F||a(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(F.inputManager||s)(e,F)}function l(){F.beginRender(),n.renderLinks&&F.renderLinks(),F.renderNodes(),F.endRender()}function p(){return X=O.step()&&!V,l(),!X}function v(e){R||(R=void 0!==e?f(function(){if(e-=1,e<0){var n=!1;return n}return p()},M):f(p,M))}function h(){W||(X=!1,R.restart())}function g(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;e0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,h(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):r=e),t},getSvgRoot:function(){return t}};return i(b),b}n.exports=r;var o=e("simplesvg"),i=e("ngraph.events"),a=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":38,"ngraph.events":9,simplesvg:32}],54:[function(e,n,t){function r(e){e=c(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,r,d,l,p,v,h,g=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=i(),N=a(),k=function(e){return u()},P=function(e){return s(3014898687)},j=function(){L.updateTransform(y),N.updateTransform(y)},A=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),r&&r.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),N&&N.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){if("function"==typeof e)return k=e,this},link:function(e){if("function"==typeof e)return P=e,this},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:o,beginRender:function(){},endRender:function(){m>0&&L.render(),g>0&&N.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,j()},addLink:function(e,n){var t=m++,r=P(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=g++,r=k(e);return r.id=t,r.position=n,r.node=e,N.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],j()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,j(),I(this),y[0]},resetScale:function(){return A(),r&&(_(),j()),this},updateSize:_,init:function(o){var i={};if(e.preserveDrawingBuffer&&(i.preserveDrawingBuffer=!0),n=o,_(),A(),n.appendChild(t),r=t.getContext("experimental-webgl",i),!r){var a="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(a),a}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var u=e.clearColorValue;r.clearColor(u.r,u.g,u.b,u.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}L.load(r),L.updateSize(d/2,l/2),N.load(r),N.updateSize(d/2,l/2),j(),"function"==typeof h&&h(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(t0&&(g-=1);var n=b[e.id];delete b[e.id],N.removeNode(n);var t=n.id;if(te.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;o=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*g,r.row*g,g,g),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/h<<0,i=r%h;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*g,i=n.row*g;r.drawImage(t,e.col*g,e.row*g,g,g,o,i,g,g),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,h=Math.sqrt(e||1024)<<0,g=h,m=1,y={},x=0,w=[],b=[];if(!o(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:r,getCoordinates:a,load:u};return E}function o(e){return 0===(e&e-1)}var i=e("./texture.js");n.exports=r},{"./texture.js":56}],59:[function(e,n,t){function r(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=r},{}],60:[function(e,n,t){function r(){function e(e,n){e.nativeObject&&g.deleteTexture(e.nativeObject);var t=g.createTexture();g.activeTexture(g["TEXTURE"+n]),g.bindTexture(g.TEXTURE_2D,t),g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,e.canvas),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MAG_FILTER,g.LINEAR),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MIN_FILTER,g.LINEAR_MIPMAP_NEAREST),g.generateMipmap(g.TEXTURE_2D),g.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(A-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*N,A*N,N))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){g.useProgram(h),g.bindBuffer(g.ARRAY_BUFFER,m),g.bufferData(g.ARRAY_BUFFER,_,g.DYNAMIC_DRAW),L&&(L=!1,g.uniformMatrix4fv(x.transform,!1,E),g.uniform2f(x.screenSize,w,b)),g.vertexAttribPointer(x.vertexPos,2,g.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),g.vertexAttribPointer(x.customAttributes,1,g.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),g.drawArrays(g.TRIANGLES,0,6*A)}var v,h,g,m,y,x,w,b,E,L,N=18,k=o(),P=i(),j=1024,A=0,_=new Float32Array(64);return{load:t,position:r,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function o(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function i(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var a=e("./webglAtlas.js"),u=e("./webgl.js");n.exports=r},{"./webgl.js":57,"./webglAtlas.js":58}],61:[function(e,n,t){function r(e){function n(){x=null}function t(e){x=e}function r(e){return"function"==typeof e&&P.push(e),A}function i(e){return"function"==typeof e&&k.push(e),A}function a(e){return"function"==typeof e&&N.push(e),A}function u(e){return"function"==typeof e&&L.push(e),A}function s(e){return"function"==typeof e&&E.push(e),A}function f(e){return"function"==typeof e&&b.push(e),A}function c(e){return"function"==typeof e&&w.push(e),A}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-og.byteLength){var e=new ArrayBuffer(2*g.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,g=e}};return{load:function(a){n=a,r=o(a),e=r.createProgram(v,p),n.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),h+=1,a=e.id},removeLink:function(e){h>0&&(h-=1),e.id0&&r.copyArrayPart(y,e.id*d,h*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,g,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*h),a=h-1},bringToFront:function(e){a>e.id&&r.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":57}],64:[function(e,n,t){function r(){function e(){if((P+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(k),N=n,k=t,L=e}}function n(e){d=e,v=o(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]), +d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;N[t*x]=n.x,N[t*x+1]=-n.y,N[t*x+2]=e.size,k[t*x+3]=e.color}function r(e){y=!0,m=e}function i(e,n){h=e,g=n,y=!0}function a(e){P>0&&(P-=1),e.id0&&v.copyArrayPart(k,e.id*x,P*x,x)}function u(){e(),P+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,h,g)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,P)}var c,d,l,p,v,h,g,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),N=new Float32Array(L),k=new Uint32Array(L),P=0;return{load:n,position:t,updateTransform:r,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":57}],65:[function(e,n,t){function r(e,n){return{size:"number"==typeof e?e:10,color:o(n)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":55}],66:[function(e,n,t){n.exports="0.8.1"},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/package.json b/package.json index 5d8ea11..9937fbf 100644 --- a/package.json +++ b/package.json @@ -35,15 +35,15 @@ }, "dependencies": { "gintersect": "0.1.0", - "ngraph.centrality": "0.1.3", + "ngraph.centrality": "0.3.0", "ngraph.events": "0.0.3", - "ngraph.forcelayout": "0.1.2", - "ngraph.fromjson": "0.1.7", - "ngraph.generators": "0.0.15", - "ngraph.graph": "0.0.11", + "ngraph.forcelayout": "0.5.0", + "ngraph.fromjson": "0.1.9", + "ngraph.generators": "0.0.19", + "ngraph.graph": "0.0.14", "ngraph.merge": "0.0.1", "ngraph.random": "0.0.1", - "ngraph.tojson": "0.1.3", + "ngraph.tojson": "0.1.4", "simplesvg": "0.0.10" } } From 580bb9af282f2511248e8cd98d7c31d35bd94c31 Mon Sep 17 00:00:00 2001 From: Andriy Kashcha Date: Sun, 25 Mar 2018 18:14:15 -0700 Subject: [PATCH 248/276] Updated travis --- .travis.yml | 2 +- README.md | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 35048b6..851fb95 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,3 @@ language: node_js node_js: -- '0.10' +- node diff --git a/README.md b/README.md index 6f72ee8..605e8ba 100644 --- a/README.md +++ b/README.md @@ -112,8 +112,7 @@ graphics.node(function(node) { nodeUI.attr('x', pos.x - 12).attr('y', pos.y - 12); }); -var renderer = Viva.Graph.View.renderer(graph, - { +var renderer = Viva.Graph.View.renderer(graph, { graphics : graphics }); renderer.run(); From 8a5925cae899acce0e8440e403cdd075aac45031 Mon Sep 17 00:00:00 2001 From: Andriy Kashcha Date: Sun, 22 Apr 2018 15:51:46 -0700 Subject: [PATCH 249/276] updated version --- src/version.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.js b/src/version.js index d55dbb2..b977700 100644 --- a/src/version.js +++ b/src/version.js @@ -1,2 +1,2 @@ // todo: this should be generated at build time. -module.exports = '0.8.1'; +module.exports = '0.10.1'; From 265fe924b9a9948e3cb3775650d23aa1968182eb Mon Sep 17 00:00:00 2001 From: Andriy Kashcha Date: Sun, 30 Dec 2018 08:23:06 -0800 Subject: [PATCH 250/276] updated years --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index c713177..ed8f60b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2011 - 2016, Andrei Kashcha +Copyright (c) 2011 - 2018, Andrei Kashcha All rights reserved. Redistribution and use in source and binary forms, with or without From 1b639d9d7406d3ecad013aff35c64567243e4aa4 Mon Sep 17 00:00:00 2001 From: Andriy Kashcha Date: Sun, 3 Mar 2019 08:58:17 -0800 Subject: [PATCH 251/276] updated years --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index ed8f60b..ce35121 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2011 - 2018, Andrei Kashcha +Copyright (c) 2011 - 2019, Andrei Kashcha All rights reserved. Redistribution and use in source and binary forms, with or without From 8d90f54937178b7953f29f1700a85119c6dbedf9 Mon Sep 17 00:00:00 2001 From: Andriy Kashcha Date: Tue, 22 Oct 2019 20:12:21 -0700 Subject: [PATCH 252/276] rebuild --- dist/vivagraph.js | 17 ++++++++++------- dist/vivagraph.min.js | 4 ++-- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 7934f28..2839752 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -4761,6 +4761,9 @@ function renderer(graph, settings) { return graphics; }, + /** + * Gets current layout. + */ getLayout: function() { return layout; }, @@ -6529,27 +6532,27 @@ function webglImageNodeProgram() { function position(nodeUI, pos) { var idx = nodeUI.id * ATTRIBUTES_PER_PRIMITIVE; nodes[idx] = pos.x - nodeUI.size; - nodes[idx + 1] = pos.y - nodeUI.size; + nodes[idx + 1] = -pos.y - nodeUI.size; nodes[idx + 2] = nodeUI._offset * 4; nodes[idx + 3] = pos.x + nodeUI.size; - nodes[idx + 4] = pos.y - nodeUI.size; + nodes[idx + 4] = -pos.y - nodeUI.size; nodes[idx + 5] = nodeUI._offset * 4 + 1; nodes[idx + 6] = pos.x - nodeUI.size; - nodes[idx + 7] = pos.y + nodeUI.size; + nodes[idx + 7] = -pos.y + nodeUI.size; nodes[idx + 8] = nodeUI._offset * 4 + 2; nodes[idx + 9] = pos.x - nodeUI.size; - nodes[idx + 10] = pos.y + nodeUI.size; + nodes[idx + 10] = -pos.y + nodeUI.size; nodes[idx + 11] = nodeUI._offset * 4 + 2; nodes[idx + 12] = pos.x + nodeUI.size; - nodes[idx + 13] = pos.y - nodeUI.size; + nodes[idx + 13] = -pos.y - nodeUI.size; nodes[idx + 14] = nodeUI._offset * 4 + 1; nodes[idx + 15] = pos.x + nodeUI.size; - nodes[idx + 16] = pos.y + nodeUI.size; + nodes[idx + 16] = -pos.y + nodeUI.size; nodes[idx + 17] = nodeUI._offset * 4 + 3; } @@ -7312,7 +7315,7 @@ function webglSquare(size, color) { },{"./parseColor.js":55}],66:[function(require,module,exports){ // todo: this should be generated at build time. -module.exports = '0.8.1'; +module.exports = '0.10.1'; },{}]},{},[1])(1) }); \ No newline at end of file diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 84f31bb..5ef7186 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,3 +1,3 @@ !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,h=f*t+d*r+p,0!==v&&0!==h&&v>=0==h>=0?null:(y=s*d-f*c,0===y?null:(x=y<0?-y/2:y/2,x=0,w=c*p-d*l,b.x=(w<0?w-x:w+x)/y,w=f*l-s*p,b.y=(w<0?w-x:w+x)/y,b)))}n.exports=r},{}],4:[function(e,n,t){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js"),n.exports.closeness=e("./src/closeness.js"),n.exports.eccentricity=e("./src/eccentricity.js")},{"./src/betweenness.js":5,"./src/closeness.js":6,"./src/degree.js":7,"./src/eccentricity.js":8}],5:[function(e,n,t){function r(e,n){function t(e){h[e]/=2}function r(e){h[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o0?f[a]=(n-1)/t:f[a]=0}function i(t){function r(e){var n=e.id;s[n]=-1}function o(e){var n=e.id;s[n]===-1&&(s[n]=s[i]+1,u.push(n))}for(e.forEachNode(r),s[t]=0,u.push(t);u.length;){var i=u.shift();e.forEachLinkedNode(i,o,n)}}var a,u=[],s=Object.create(null),f=Object.create(null);return e.forEachNode(t),e.forEachNode(r),f}n.exports=r},{}],7:[function(e,n,t){function r(e,n){function t(n){var t=e.getLinks(n.id);u[n.id]=r(t,n.id)}var r,u=Object.create(null);if(n=(n||"both").toLowerCase(),"both"===n||"inout"===n)r=a;else if("in"===n)r=o;else{if("out"!==n)throw new Error("Expected centrality degree kind is: in, out or both");r=i}return e.forEachNode(t),u}function o(e,n){var t=0;if(!e)return t;for(var r=0;r1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;i0&&i.addLink(a,r-1+o*e),o>0&&i.addLink(a,r+(o-1)*e)}return i}function s(e,t,r){if(e<1||t<1||r<1)throw new Error("Invalid number of nodes in grid3 graph");var o,i,a,u=n();if(1===e&&1===t&&1===r)return u.addNode(0),u;for(a=0;a0&&u.addLink(f,o-1+i*e+s),i>0&&u.addLink(f,o+(i-1)*e+s),a>0&&u.addLink(f,o+i*e+(a-1)*e*t)}return u}function f(e){if(e<0)throw new Error("Invalid number of nodes in balanced tree");var t,r=n(),o=Math.pow(2,e);for(0===e&&r.addNode(1),t=1;t= 0");var t,r=n();for(t=0;t0&&o.addLink(i*t,i*t-1);return o.addLink(0,o.getNodesCount()-1),o}function l(t,r,o,i){if(r>=t)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var a,u,s=e("ngraph.random").random(i||42),f=n();for(a=0;a=1||0===e);return n*Math.sqrt(-2*Math.log(e)/e)}function a(){var e=this.seed;return e=e+2127912214+(e<<12)&4294967295,e=4294967295&(3345072700^e^e>>>19),e=e+374761393+(e<<5)&4294967295,e=4294967295&(e+3550635116^e<<9),e=e+4251993797+(e<<3)&4294967295,e=4294967295&(3042594569^e^e>>>16),this.seed=e,(268435455&e)/268435456}function u(e){return Math.floor(this.nextDouble()*e)}function s(e,n){function t(){var n,t,r;for(n=e.length-1;n>0;--n)t=i.next(n+1),r=e[t],e[t]=e[n],e[n]=r;return e}function o(n){var t,r,o;for(t=e.length-1;t>0;--t)r=i.next(t+1),o=e[r],e[r]=e[t],e[t]=o,n(o);e.length&&n(e[0])}var i=n||r();if("function"!=typeof i.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:o,shuffle:t}}n.exports=r,n.exports.random=r,n.exports.randomIterator=s,o.prototype.next=u,o.prototype.nextDouble=a,o.prototype.uniform=a,o.prototype.gaussian=i},{}],16:[function(e,n,t){function r(e){function n(){function e(){return q.beginUpdate=F=k,q.endUpdate=G=P,B=t,O=r,q.on=n,n.apply(q,arguments)}var n=q.on;q.on=e}function t(e,n){R.push({link:e,changeType:n})}function r(e,n){R.push({node:e,changeType:n})}function c(e,n){if(void 0===e)throw new Error("Invalid node identifier");F();var t=d(e);return t?(t.data=n,O(t,"update")):(t=new i(e,n),S++,O(t,"add")),I[e]=t,G(),t}function d(e){return I[e]}function l(e){var n=d(e);if(!n)return!1;F();var t=n.links;if(t){n.links=null;for(var r=0;r=0&&t.links.splice(n,1)),r&&(n=o(e,r.links),n>=0&&r.links.splice(n,1)),B(e,"remove"),G(),!0}function y(e,n){var t,r=d(e);if(!r||!r.links)return null;for(t=0;t0&&(q.fire("changed",R),R.length=0)}function j(){return Object.keys?A:_}function A(e){if("function"==typeof e)for(var n=Object.keys(I),t=0;t=0?i:-1,o);return v.push(a),a},getTotalMovement:function(){return w},removeSpring:function(e){if(e){var n=v.indexOf(e);return n>-1?(v.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return x&&(g.update(),x=!1),g.box},invalidateBBox:function(){x=!0},gravity:function(e){return void 0!==e?(n.gravity=e,h.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,h.options({theta:e}),this):n.theta}};return o(n,b),a(b),b}n.exports=r},{"./lib/bounds":20,"./lib/createBody":21,"./lib/dragForce":22,"./lib/eulerIntegrator":23,"./lib/spring":24,"./lib/springForce":25,"ngraph.events":9,"ngraph.expose":10,"ngraph.merge":17,"ngraph.quadtreebh":26}],20:[function(e,n,t){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;u1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/u}n.exports=r},{}],24:[function(e,n,t){function r(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=r},{}],25:[function(e,n,t){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":10,"ngraph.merge":17,"ngraph.random":30}],26:[function(e,n,t){function r(e,n){return 0===n?e.quad0:1===n?e.quad1:2===n?e.quad2:3===n?e.quad3:null}function o(e,n,t){0===n?e.quad0=t:1===n?e.quad1=t:2===n?e.quad2=t:3===n&&(e.quad3=t)}n.exports=function(n){function t(){var e=g[m];return e?(e.quad0=null,e.quad1=null,e.quad2=null,e.quad3=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0):(e=new f,g[m]=e),++m,e}function i(e){var n,t,r,o,i=p,a=0,u=0,f=1,c=0,d=1;for(i[0]=y;f;){var v=i[c],g=v.body;f-=1,c+=1;var m=g!==e;g&&m?(t=g.pos.x-e.pos.x,r=g.pos.y-e.pos.y,o=Math.sqrt(t*t+r*r),0===o&&(t=(s.nextDouble()-.5)/50,r=(s.nextDouble()-.5)/50,o=Math.sqrt(t*t+r*r)),n=l*g.mass*e.mass/(o*o*o),a+=n*t,u+=n*r):m&&(t=v.massX/v.mass-e.pos.x,r=v.massY/v.mass-e.pos.y,o=Math.sqrt(t*t+r*r),0===o&&(t=(s.nextDouble()-.5)/50,r=(s.nextDouble()-.5)/50,o=Math.sqrt(t*t+r*r)),(v.right-v.left)/oi&&(i=f),ca&&(a=c)}var d=i-r,l=a-o;for(d>l?a=o+d:i=r+l,m=0,y=t(),y.left=r,y.right=i,y.top=o,y.bottom=a,n=s-1,n>=0&&(y.body=e[n]);n--;)u(e[n],y)}function u(e){for(v.reset(),v.push(y,e);!v.isEmpty();){var n=v.pop(),i=n.node,a=n.body;if(i.body){var u=i.body;if(i.body=null,d(u.pos,a.pos)){var f=3;do{var c=s.nextDouble(),l=(i.right-i.left)*c,p=(i.bottom-i.top)*c;u.pos.x=i.left+l,u.pos.y=i.top+p,f-=1}while(f>0&&d(u.pos,a.pos));if(0===f&&d(u.pos,a.pos))return}v.push(i,u),v.push(i,a)}else{var h=a.pos.x,g=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*h,i.massY=i.massY+a.mass*g;var m=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;h>w&&(m+=1,x=w,w=i.right),g>E&&(m+=2,b=E,E=i.bottom);var L=r(i,m);L?v.push(L,a):(L=t(),L.left=x,L.top=b,L.right=w,L.bottom=E,L.body=a,o(i,m,L))}}}n=n||{},n.gravity="number"==typeof n.gravity?n.gravity:-1,n.theta="number"==typeof n.theta?n.theta:.8;var s=e("ngraph.random").random(1984),f=e("./node"),c=e("./insertStack"),d=e("./isSamePosition"),l=n.gravity,p=[],v=new c,h=n.theta,g=[],m=0,y=t();return{insertBodies:a,getRoot:function(){return y},updateBodyForce:i,options:function(e){return e?("number"==typeof e.gravity&&(l=e.gravity),"number"==typeof e.theta&&(h=e.theta),this):{gravity:l,theta:h}}}}},{"./insertStack":27,"./isSamePosition":28,"./node":29,"ngraph.random":30}],27:[function(e,n,t){function r(){this.stack=[],this.popIdx=0}function o(e,n){this.node=e,this.body=n}n.exports=r,r.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new o(e,n),++this.popIdx},pop:function(){if(this.popIdx>0)return this.stack[--this.popIdx]},reset:function(){this.popIdx=0}}},{}],28:[function(e,n,t){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return t<1e-8&&r<1e-8}},{}],29:[function(e,n,t){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],30:[function(e,n,t){function r(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function o(e,n){var t=n||r();if("function"!=typeof t.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var r,o,i;for(r=e.length-1;r>0;--r)o=t.next(r+1),i=e[o],e[o]=e[r],e[r]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,r,o;for(n=e.length-1;n>0;--n)r=t.next(n+1),o=e[r],e[r]=e[n],e[n]=o;return e}}}n.exports={random:r,randomIterator:o}},{}],31:[function(e,n,t){function r(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=r},{}],32:[function(e,n,t){function r(e,n){var t=o(e);if(void 0===n)return t;for(var r=Object.keys(n),i=0;iv&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},j=function(e){p=!1,o.off("touchmove",P),o.off("touchend",j),o.off("touchcancel",j),c=null,r&&r(e)},A=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,o.on("touchmove",P),o.on("touchend",j),o.on("touchcancel",j))},_=function(e){return 1===e.touches.length?A(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=k(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),o.off("mousemove",w),o.off("mouseup",E),o.off("touchmove",P),o.off("touchend",j),o.off("touchcancel",j),N(null)}}}n.exports=r;var o=e("../Utils/documentEvents.js"),i=e("../Utils/browserInfo.js"),a=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":43,"../Utils/documentEvents.js":44,"../Utils/findElementPosition.js":45}],40:[function(e,n,t){function r(e,n){var t=o(n),r=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){r=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(r);var o=i[e.id];return o&&o.onStart&&o.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(r),r=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(r){var t=i[r.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=r;var o=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":61}],41:[function(e,n,t){function r(e,n){function t(e){return d[e]}n=o(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var r=i(n.seed),u=new a(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(e){return{x:r.next(n.maxX),y:r.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},h=function(e){for(var n=0;n=0:"boolean"!=typeof q||q}function r(){G=G||window.document.body,O=O||i(e,{springLength:80,springCoeff:2e-4}),F=F||a(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(F.inputManager||s)(e,F)}function l(){F.beginRender(),n.renderLinks&&F.renderLinks(),F.renderNodes(),F.endRender()}function p(){return X=O.step()&&!V,l(),!X}function v(e){R||(R=void 0!==e?f(function(){if(e-=1,e<0){var n=!1;return n}return p()},M):f(p,M))}function h(){W||(X=!1,R.restart())}function g(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;e0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,h(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):r=e),t},getSvgRoot:function(){return t}};return i(b),b}n.exports=r;var o=e("simplesvg"),i=e("ngraph.events"),a=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":38,"ngraph.events":9,simplesvg:32}],54:[function(e,n,t){function r(e){e=c(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,r,d,l,p,v,h,g=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=i(),N=a(),k=function(e){return u()},P=function(e){return s(3014898687)},j=function(){L.updateTransform(y),N.updateTransform(y)},A=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),r&&r.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),N&&N.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){if("function"==typeof e)return k=e,this},link:function(e){if("function"==typeof e)return P=e,this},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:o,beginRender:function(){},endRender:function(){m>0&&L.render(),g>0&&N.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,j()},addLink:function(e,n){var t=m++,r=P(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=g++,r=k(e);return r.id=t,r.position=n,r.node=e,N.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],j()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,j(),I(this),y[0]},resetScale:function(){return A(),r&&(_(),j()),this},updateSize:_,init:function(o){var i={};if(e.preserveDrawingBuffer&&(i.preserveDrawingBuffer=!0),n=o,_(),A(),n.appendChild(t),r=t.getContext("experimental-webgl",i),!r){var a="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(a),a}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var u=e.clearColorValue;r.clearColor(u.r,u.g,u.b,u.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}L.load(r),L.updateSize(d/2,l/2),N.load(r),N.updateSize(d/2,l/2),j(),"function"==typeof h&&h(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(t0&&(g-=1);var n=b[e.id];delete b[e.id],N.removeNode(n);var t=n.id;if(te.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;o=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*g,r.row*g,g,g),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/h<<0,i=r%h;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*g,i=n.row*g;r.drawImage(t,e.col*g,e.row*g,g,g,o,i,g,g),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,h=Math.sqrt(e||1024)<<0,g=h,m=1,y={},x=0,w=[],b=[];if(!o(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:r,getCoordinates:a,load:u};return E}function o(e){return 0===(e&e-1)}var i=e("./texture.js");n.exports=r},{"./texture.js":56}],59:[function(e,n,t){function r(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=r},{}],60:[function(e,n,t){function r(){function e(e,n){e.nativeObject&&g.deleteTexture(e.nativeObject);var t=g.createTexture();g.activeTexture(g["TEXTURE"+n]),g.bindTexture(g.TEXTURE_2D,t),g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,e.canvas),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MAG_FILTER,g.LINEAR),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MIN_FILTER,g.LINEAR_MIPMAP_NEAREST),g.generateMipmap(g.TEXTURE_2D),g.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(A-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*N,A*N,N))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){g.useProgram(h),g.bindBuffer(g.ARRAY_BUFFER,m),g.bufferData(g.ARRAY_BUFFER,_,g.DYNAMIC_DRAW),L&&(L=!1,g.uniformMatrix4fv(x.transform,!1,E),g.uniform2f(x.screenSize,w,b)),g.vertexAttribPointer(x.vertexPos,2,g.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),g.vertexAttribPointer(x.customAttributes,1,g.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),g.drawArrays(g.TRIANGLES,0,6*A)}var v,h,g,m,y,x,w,b,E,L,N=18,k=o(),P=i(),j=1024,A=0,_=new Float32Array(64);return{load:t,position:r,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function o(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function i(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var a=e("./webglAtlas.js"),u=e("./webgl.js");n.exports=r},{"./webgl.js":57,"./webglAtlas.js":58}],61:[function(e,n,t){function r(e){function n(){x=null}function t(e){x=e}function r(e){return"function"==typeof e&&P.push(e),A}function i(e){return"function"==typeof e&&k.push(e),A}function a(e){return"function"==typeof e&&N.push(e),A}function u(e){return"function"==typeof e&&L.push(e),A}function s(e){return"function"==typeof e&&E.push(e),A}function f(e){return"function"==typeof e&&b.push(e),A}function c(e){return"function"==typeof e&&w.push(e),A}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-og.byteLength){var e=new ArrayBuffer(2*g.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,g=e}};return{load:function(a){n=a,r=o(a),e=r.createProgram(v,p),n.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),h+=1,a=e.id},removeLink:function(e){h>0&&(h-=1),e.id0&&r.copyArrayPart(y,e.id*d,h*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,g,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*h),a=h-1},bringToFront:function(e){a>e.id&&r.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":57}],64:[function(e,n,t){function r(){function e(){if((P+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(k),N=n,k=t,L=e}}function n(e){d=e,v=o(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]), -d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;N[t*x]=n.x,N[t*x+1]=-n.y,N[t*x+2]=e.size,k[t*x+3]=e.color}function r(e){y=!0,m=e}function i(e,n){h=e,g=n,y=!0}function a(e){P>0&&(P-=1),e.id0&&v.copyArrayPart(k,e.id*x,P*x,x)}function u(){e(),P+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,h,g)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,P)}var c,d,l,p,v,h,g,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),N=new Float32Array(L),k=new Uint32Array(L),P=0;return{load:n,position:t,updateTransform:r,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":57}],65:[function(e,n,t){function r(e,n){return{size:"number"==typeof e?e:10,color:o(n)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":55}],66:[function(e,n,t){n.exports="0.8.1"},{}]},{},[1])(1)}); \ No newline at end of file +n[i]);a?a.push(t):a=n[i]=[t]}}}n.exports=r;var u=/{{(.+?)}}/},{}],35:[function(e,n,t){function r(){return"undefined"==typeof DOMParser?{parseFromString:o}:new DOMParser}function o(){throw new Error("DOMParser is not supported by this platform. Please open issue here https://github.com/anvaka/simplesvg")}n.exports=r()},{}],36:[function(e,n,t){function r(){return{betweennessCentrality:o,degreeCentrality:i}}function o(e){var n=u.betweenness(e);return a(n)}function i(e,n){var t=u.degree(e,n);return a(t)}function a(e){function n(n,t){return e[t]-e[n]}function t(n){return{key:n,value:e[n]}}return Object.keys(e).sort(n).map(t)}var u=e("ngraph.centrality");n.exports=r},{"ngraph.centrality":4}],37:[function(e,n,t){function r(){return{density:function(e,n){var t=e.getNodesCount();return 0===t?NaN:n?e.getLinksCount()/(t*(t-1)):2*e.getLinksCount()/(t*(t-1))}}}n.exports=r},{}],38:[function(e,n,t){function r(e,n){function t(e,t){var i;if(t){var a=n.getNodeUI(e.id);i=o(a),"function"==typeof t.onStart&&i.onStart(t.onStart),"function"==typeof t.onDrag&&i.onDrag(t.onDrag),"function"==typeof t.onStop&&i.onStop(t.onStop),r[e.id]=i}else(i=r[e.id])&&(i.release(),delete r[e.id])}var r={};return{bindDragNDrop:t}}n.exports=r;var o=e("./dragndrop.js")},{"./dragndrop.js":39}],39:[function(e,n,t){function r(e){var n,t,r,u,s,f,c,d=0,l=0,p=!1,v=0,h=function(e){var n=0,t=0;return e=e||window.event,e.pageX||e.pageY?(n=e.pageX,t=e.pageY):(e.clientX||e.clientY)&&(n=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,t=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[n,t]},g=function(e,n,r){t&&t(e,{x:n-d,y:r-l}),d=n,l=r},m=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return m(e),!1},w=function(e){e=e||window.event,g(e,e.clientX,e.clientY)},b=function(e){if(e=e||window.event,p)return m(e),!1;var t=1===e.button&&null!==window.event||0===e.button;return t?(d=e.clientX,l=e.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),o.on("mousemove",w),o.on("mouseup",E),m(e),s=window.document.onselectstart,f=window.document.ondragstart,window.document.onselectstart=x,c.ondragstart=x,!1):void 0},E=function(e){e=e||window.event,o.off("mousemove",w),o.off("mouseup",E),window.document.onselectstart=s,c.ondragstart=f,c=null,r&&r(e)},L=function(n){if("function"==typeof u){n=n||window.event,n.preventDefault&&n.preventDefault(),n.returnValue=!1;var t,r=h(n),o=a(e),i={x:r[0]-o[0],y:r[1]-o[1]};t=n.wheelDelta?n.wheelDelta/360:n.detail/-9,u(n,t,i)}},N=function(n){!u&&n?"webkit"===i.browser?e.addEventListener("mousewheel",L,!1):e.addEventListener("DOMMouseScroll",L,!1):u&&!n&&("webkit"===i.browser?e.removeEventListener("mousewheel",L,!1):e.removeEventListener("DOMMouseScroll",L,!1)),u=n},k=function(e,n){return(e.clientX-n.clientX)*(e.clientX-n.clientX)+(e.clientY-n.clientY)*(e.clientY-n.clientY)},P=function(e){if(1===e.touches.length){m(e);var n=e.touches[0];g(e,n.clientX,n.clientY)}else if(2===e.touches.length){var t=k(e.touches[0],e.touches[1]),r=0;tv&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},j=function(e){p=!1,o.off("touchmove",P),o.off("touchend",j),o.off("touchcancel",j),c=null,r&&r(e)},A=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,o.on("touchmove",P),o.on("touchend",j),o.on("touchcancel",j))},_=function(e){return 1===e.touches.length?A(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=k(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),o.off("mousemove",w),o.off("mouseup",E),o.off("touchmove",P),o.off("touchend",j),o.off("touchcancel",j),N(null)}}}n.exports=r;var o=e("../Utils/documentEvents.js"),i=e("../Utils/browserInfo.js"),a=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":43,"../Utils/documentEvents.js":44,"../Utils/findElementPosition.js":45}],40:[function(e,n,t){function r(e,n){var t=o(n),r=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){r=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(r);var o=i[e.id];return o&&o.onStart&&o.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(r),r=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(r){var t=i[r.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=r;var o=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":61}],41:[function(e,n,t){function r(e,n){function t(e){return d[e]}n=o(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var r=i(n.seed),u=new a(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(e){return{x:r.next(n.maxX),y:r.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},h=function(e){for(var n=0;n=0:"boolean"!=typeof q||q}function r(){G=G||window.document.body,O=O||i(e,{springLength:80,springCoeff:2e-4}),F=F||a(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(F.inputManager||s)(e,F)}function l(){F.beginRender(),n.renderLinks&&F.renderLinks(),F.renderNodes(),F.endRender()}function p(){return X=O.step()&&!V,l(),!X}function v(e){R||(R=void 0!==e?f(function(){if(e-=1,e<0){var n=!1;return n}return p()},M):f(p,M))}function h(){W||(X=!1,R.restart())}function g(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;e0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,h(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):r=e),t},getSvgRoot:function(){return t}};return i(b),b}n.exports=r;var o=e("simplesvg"),i=e("ngraph.events"),a=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":38,"ngraph.events":9,simplesvg:32}],54:[function(e,n,t){function r(e){e=c(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,r,d,l,p,v,h,g=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=i(),N=a(),k=function(e){return u()},P=function(e){return s(3014898687)},j=function(){L.updateTransform(y),N.updateTransform(y)},A=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),r&&r.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),N&&N.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){if("function"==typeof e)return k=e,this},link:function(e){if("function"==typeof e)return P=e,this},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:o,beginRender:function(){},endRender:function(){m>0&&L.render(),g>0&&N.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,j()},addLink:function(e,n){var t=m++,r=P(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=g++,r=k(e);return r.id=t,r.position=n,r.node=e,N.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],j()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,j(),I(this),y[0]},resetScale:function(){return A(),r&&(_(),j()),this},updateSize:_,init:function(o){var i={};if(e.preserveDrawingBuffer&&(i.preserveDrawingBuffer=!0),n=o,_(),A(),n.appendChild(t),r=t.getContext("experimental-webgl",i),!r){var a="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(a),a}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var u=e.clearColorValue;r.clearColor(u.r,u.g,u.b,u.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}L.load(r),L.updateSize(d/2,l/2),N.load(r),N.updateSize(d/2,l/2),j(),"function"==typeof h&&h(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(t0&&(g-=1);var n=b[e.id];delete b[e.id],N.removeNode(n);var t=n.id;if(te.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;o=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*g,r.row*g,g,g),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/h<<0,i=r%h;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*g,i=n.row*g;r.drawImage(t,e.col*g,e.row*g,g,g,o,i,g,g),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,h=Math.sqrt(e||1024)<<0,g=h,m=1,y={},x=0,w=[],b=[];if(!o(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:r,getCoordinates:a,load:u};return E}function o(e){return 0===(e&e-1)}var i=e("./texture.js");n.exports=r},{"./texture.js":56}],59:[function(e,n,t){function r(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=r},{}],60:[function(e,n,t){function r(){function e(e,n){e.nativeObject&&g.deleteTexture(e.nativeObject);var t=g.createTexture();g.activeTexture(g["TEXTURE"+n]),g.bindTexture(g.TEXTURE_2D,t),g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,e.canvas),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MAG_FILTER,g.LINEAR),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MIN_FILTER,g.LINEAR_MIPMAP_NEAREST),g.generateMipmap(g.TEXTURE_2D),g.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(A-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*N,A*N,N))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){g.useProgram(h),g.bindBuffer(g.ARRAY_BUFFER,m),g.bufferData(g.ARRAY_BUFFER,_,g.DYNAMIC_DRAW),L&&(L=!1,g.uniformMatrix4fv(x.transform,!1,E),g.uniform2f(x.screenSize,w,b)),g.vertexAttribPointer(x.vertexPos,2,g.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),g.vertexAttribPointer(x.customAttributes,1,g.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),g.drawArrays(g.TRIANGLES,0,6*A)}var v,h,g,m,y,x,w,b,E,L,N=18,k=o(),P=i(),j=1024,A=0,_=new Float32Array(64);return{load:t,position:r,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function o(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function i(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var a=e("./webglAtlas.js"),u=e("./webgl.js");n.exports=r},{"./webgl.js":57,"./webglAtlas.js":58}],61:[function(e,n,t){function r(e){function n(){x=null}function t(e){x=e}function r(e){return"function"==typeof e&&P.push(e),A}function i(e){return"function"==typeof e&&k.push(e),A}function a(e){return"function"==typeof e&&N.push(e),A}function u(e){return"function"==typeof e&&L.push(e),A}function s(e){return"function"==typeof e&&E.push(e),A}function f(e){return"function"==typeof e&&b.push(e),A}function c(e){return"function"==typeof e&&w.push(e),A}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-og.byteLength){var e=new ArrayBuffer(2*g.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,g=e}};return{load:function(a){n=a,r=o(a),e=r.createProgram(v,p),n.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),h+=1,a=e.id},removeLink:function(e){h>0&&(h-=1),e.id0&&r.copyArrayPart(y,e.id*d,h*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,g,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*h),a=h-1},bringToFront:function(e){a>e.id&&r.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":57}],64:[function(e,n,t){function r(){function e(){if((P+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(k),N=n,k=t,L=e}}function n(e){d=e,v=o(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]), +d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;N[t*x]=n.x,N[t*x+1]=-n.y,N[t*x+2]=e.size,k[t*x+3]=e.color}function r(e){y=!0,m=e}function i(e,n){h=e,g=n,y=!0}function a(e){P>0&&(P-=1),e.id0&&v.copyArrayPart(k,e.id*x,P*x,x)}function u(){e(),P+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,h,g)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,P)}var c,d,l,p,v,h,g,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),N=new Float32Array(L),k=new Uint32Array(L),P=0;return{load:n,position:t,updateTransform:r,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":57}],65:[function(e,n,t){function r(e,n){return{size:"number"==typeof e?e:10,color:o(n)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":55}],66:[function(e,n,t){n.exports="0.10.1"},{}]},{},[1])(1)}); \ No newline at end of file From fccdfe9bdb82ea68b5a769206eb55cd12dfa92ef Mon Sep 17 00:00:00 2001 From: Andriy Kashcha Date: Tue, 22 Oct 2019 20:12:37 -0700 Subject: [PATCH 253/276] 0.11.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9937fbf..763d3de 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.10.1", + "version": "0.11.0", "description": "Graph Drawing Library", "main": "src/viva", "directories": { From 8a8f536f69e9d5825e26e941d79f3b7b1389eb74 Mon Sep 17 00:00:00 2001 From: Joaquin Lovera Date: Wed, 23 Oct 2019 17:24:32 +0200 Subject: [PATCH 254/276] Optional parameter "tilesPerTexture" to webglImageNodeProgram() function --- src/WebGL/webglImageNodeProgram.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/WebGL/webglImageNodeProgram.js b/src/WebGL/webglImageNodeProgram.js index 68d8547..bb0d53d 100644 --- a/src/WebGL/webglImageNodeProgram.js +++ b/src/WebGL/webglImageNodeProgram.js @@ -12,13 +12,16 @@ module.exports = webglImageNodeProgram; /** * Defines simple UI for nodes in webgl renderer. Each node is rendered as an image. + * + * @param {number} tilesPerTexture + * */ -function webglImageNodeProgram() { +function webglImageNodeProgram(tilesPerTexture) { // WebGL is gian state machine, we store some properties of the state here: var ATTRIBUTES_PER_PRIMITIVE = 18; var nodesFS = createNodeFragmentShader(); var nodesVS = createNodeVertexShader(); - var tilesPerTexture = 1024; // TODO: Get based on max texture size + var tilesPerTexture = tilesPerTexture || 1024; // TODO: Get based on max texture size var atlas; var program; var gl; From c3e91bf819a8142939eb06fe3e961fd57d69916e Mon Sep 17 00:00:00 2001 From: Joaquin Lovera Date: Thu, 24 Oct 2019 13:31:19 +0200 Subject: [PATCH 255/276] Fixed error when two or more nodes are join, mouse leave event don't work right because only emit the mouse leave event of the last node --- src/WebGL/webglInputEvents.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/WebGL/webglInputEvents.js b/src/WebGL/webglInputEvents.js index a4654f1..381b80b 100644 --- a/src/WebGL/webglInputEvents.js +++ b/src/WebGL/webglInputEvents.js @@ -188,6 +188,9 @@ function webglInputEvents(webglGraphics) { node = getNodeAtClientPos(pos); if (node && lastFound !== node) { + if(lastFound){ + invoke(mouseLeaveCallback, [lastFound]); + } lastFound = node; cancelBubble = cancelBubble || invoke(mouseEnterCallback, [lastFound]); } else if (node === null && lastFound !== node) { From bce42fc4390e4257aad715a3e1ed702bb80f2228 Mon Sep 17 00:00:00 2001 From: Andriy Kashcha Date: Sun, 27 Oct 2019 14:23:06 -0700 Subject: [PATCH 256/276] rebuilt --- dist/vivagraph.js | 10 +- dist/vivagraph.min.js | 4 +- package-lock.json | 4582 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 4592 insertions(+), 4 deletions(-) create mode 100644 package-lock.json diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 2839752..8124757 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -6434,13 +6434,16 @@ module.exports = webglImageNodeProgram; /** * Defines simple UI for nodes in webgl renderer. Each node is rendered as an image. + * + * @param {number} tilesPerTexture + * */ -function webglImageNodeProgram() { +function webglImageNodeProgram(tilesPerTexture) { // WebGL is gian state machine, we store some properties of the state here: var ATTRIBUTES_PER_PRIMITIVE = 18; var nodesFS = createNodeFragmentShader(); var nodesVS = createNodeVertexShader(); - var tilesPerTexture = 1024; // TODO: Get based on max texture size + var tilesPerTexture = tilesPerTexture || 1024; // TODO: Get based on max texture size var atlas; var program; var gl; @@ -6874,6 +6877,9 @@ function webglInputEvents(webglGraphics) { node = getNodeAtClientPos(pos); if (node && lastFound !== node) { + if(lastFound){ + invoke(mouseLeaveCallback, [lastFound]); + } lastFound = node; cancelBubble = cancelBubble || invoke(mouseEnterCallback, [lastFound]); } else if (node === null && lastFound !== node) { diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 5ef7186..6872ddd 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,3 +1,3 @@ !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,h=f*t+d*r+p,0!==v&&0!==h&&v>=0==h>=0?null:(y=s*d-f*c,0===y?null:(x=y<0?-y/2:y/2,x=0,w=c*p-d*l,b.x=(w<0?w-x:w+x)/y,w=f*l-s*p,b.y=(w<0?w-x:w+x)/y,b)))}n.exports=r},{}],4:[function(e,n,t){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js"),n.exports.closeness=e("./src/closeness.js"),n.exports.eccentricity=e("./src/eccentricity.js")},{"./src/betweenness.js":5,"./src/closeness.js":6,"./src/degree.js":7,"./src/eccentricity.js":8}],5:[function(e,n,t){function r(e,n){function t(e){h[e]/=2}function r(e){h[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o0?f[a]=(n-1)/t:f[a]=0}function i(t){function r(e){var n=e.id;s[n]=-1}function o(e){var n=e.id;s[n]===-1&&(s[n]=s[i]+1,u.push(n))}for(e.forEachNode(r),s[t]=0,u.push(t);u.length;){var i=u.shift();e.forEachLinkedNode(i,o,n)}}var a,u=[],s=Object.create(null),f=Object.create(null);return e.forEachNode(t),e.forEachNode(r),f}n.exports=r},{}],7:[function(e,n,t){function r(e,n){function t(n){var t=e.getLinks(n.id);u[n.id]=r(t,n.id)}var r,u=Object.create(null);if(n=(n||"both").toLowerCase(),"both"===n||"inout"===n)r=a;else if("in"===n)r=o;else{if("out"!==n)throw new Error("Expected centrality degree kind is: in, out or both");r=i}return e.forEachNode(t),u}function o(e,n){var t=0;if(!e)return t;for(var r=0;r1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;i0&&i.addLink(a,r-1+o*e),o>0&&i.addLink(a,r+(o-1)*e)}return i}function s(e,t,r){if(e<1||t<1||r<1)throw new Error("Invalid number of nodes in grid3 graph");var o,i,a,u=n();if(1===e&&1===t&&1===r)return u.addNode(0),u;for(a=0;a0&&u.addLink(f,o-1+i*e+s),i>0&&u.addLink(f,o+(i-1)*e+s),a>0&&u.addLink(f,o+i*e+(a-1)*e*t)}return u}function f(e){if(e<0)throw new Error("Invalid number of nodes in balanced tree");var t,r=n(),o=Math.pow(2,e);for(0===e&&r.addNode(1),t=1;t= 0");var t,r=n();for(t=0;t0&&o.addLink(i*t,i*t-1);return o.addLink(0,o.getNodesCount()-1),o}function l(t,r,o,i){if(r>=t)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var a,u,s=e("ngraph.random").random(i||42),f=n();for(a=0;a=1||0===e);return n*Math.sqrt(-2*Math.log(e)/e)}function a(){var e=this.seed;return e=e+2127912214+(e<<12)&4294967295,e=4294967295&(3345072700^e^e>>>19),e=e+374761393+(e<<5)&4294967295,e=4294967295&(e+3550635116^e<<9),e=e+4251993797+(e<<3)&4294967295,e=4294967295&(3042594569^e^e>>>16),this.seed=e,(268435455&e)/268435456}function u(e){return Math.floor(this.nextDouble()*e)}function s(e,n){function t(){var n,t,r;for(n=e.length-1;n>0;--n)t=i.next(n+1),r=e[t],e[t]=e[n],e[n]=r;return e}function o(n){var t,r,o;for(t=e.length-1;t>0;--t)r=i.next(t+1),o=e[r],e[r]=e[t],e[t]=o,n(o);e.length&&n(e[0])}var i=n||r();if("function"!=typeof i.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:o,shuffle:t}}n.exports=r,n.exports.random=r,n.exports.randomIterator=s,o.prototype.next=u,o.prototype.nextDouble=a,o.prototype.uniform=a,o.prototype.gaussian=i},{}],16:[function(e,n,t){function r(e){function n(){function e(){return q.beginUpdate=F=k,q.endUpdate=G=P,B=t,O=r,q.on=n,n.apply(q,arguments)}var n=q.on;q.on=e}function t(e,n){R.push({link:e,changeType:n})}function r(e,n){R.push({node:e,changeType:n})}function c(e,n){if(void 0===e)throw new Error("Invalid node identifier");F();var t=d(e);return t?(t.data=n,O(t,"update")):(t=new i(e,n),S++,O(t,"add")),I[e]=t,G(),t}function d(e){return I[e]}function l(e){var n=d(e);if(!n)return!1;F();var t=n.links;if(t){n.links=null;for(var r=0;r=0&&t.links.splice(n,1)),r&&(n=o(e,r.links),n>=0&&r.links.splice(n,1)),B(e,"remove"),G(),!0}function y(e,n){var t,r=d(e);if(!r||!r.links)return null;for(t=0;t0&&(q.fire("changed",R),R.length=0)}function j(){return Object.keys?A:_}function A(e){if("function"==typeof e)for(var n=Object.keys(I),t=0;t=0?i:-1,o);return v.push(a),a},getTotalMovement:function(){return w},removeSpring:function(e){if(e){var n=v.indexOf(e);return n>-1?(v.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return x&&(g.update(),x=!1),g.box},invalidateBBox:function(){x=!0},gravity:function(e){return void 0!==e?(n.gravity=e,h.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,h.options({theta:e}),this):n.theta}};return o(n,b),a(b),b}n.exports=r},{"./lib/bounds":20,"./lib/createBody":21,"./lib/dragForce":22,"./lib/eulerIntegrator":23,"./lib/spring":24,"./lib/springForce":25,"ngraph.events":9,"ngraph.expose":10,"ngraph.merge":17,"ngraph.quadtreebh":26}],20:[function(e,n,t){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;u1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/u}n.exports=r},{}],24:[function(e,n,t){function r(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=r},{}],25:[function(e,n,t){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":10,"ngraph.merge":17,"ngraph.random":30}],26:[function(e,n,t){function r(e,n){return 0===n?e.quad0:1===n?e.quad1:2===n?e.quad2:3===n?e.quad3:null}function o(e,n,t){0===n?e.quad0=t:1===n?e.quad1=t:2===n?e.quad2=t:3===n&&(e.quad3=t)}n.exports=function(n){function t(){var e=g[m];return e?(e.quad0=null,e.quad1=null,e.quad2=null,e.quad3=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0):(e=new f,g[m]=e),++m,e}function i(e){var n,t,r,o,i=p,a=0,u=0,f=1,c=0,d=1;for(i[0]=y;f;){var v=i[c],g=v.body;f-=1,c+=1;var m=g!==e;g&&m?(t=g.pos.x-e.pos.x,r=g.pos.y-e.pos.y,o=Math.sqrt(t*t+r*r),0===o&&(t=(s.nextDouble()-.5)/50,r=(s.nextDouble()-.5)/50,o=Math.sqrt(t*t+r*r)),n=l*g.mass*e.mass/(o*o*o),a+=n*t,u+=n*r):m&&(t=v.massX/v.mass-e.pos.x,r=v.massY/v.mass-e.pos.y,o=Math.sqrt(t*t+r*r),0===o&&(t=(s.nextDouble()-.5)/50,r=(s.nextDouble()-.5)/50,o=Math.sqrt(t*t+r*r)),(v.right-v.left)/oi&&(i=f),ca&&(a=c)}var d=i-r,l=a-o;for(d>l?a=o+d:i=r+l,m=0,y=t(),y.left=r,y.right=i,y.top=o,y.bottom=a,n=s-1,n>=0&&(y.body=e[n]);n--;)u(e[n],y)}function u(e){for(v.reset(),v.push(y,e);!v.isEmpty();){var n=v.pop(),i=n.node,a=n.body;if(i.body){var u=i.body;if(i.body=null,d(u.pos,a.pos)){var f=3;do{var c=s.nextDouble(),l=(i.right-i.left)*c,p=(i.bottom-i.top)*c;u.pos.x=i.left+l,u.pos.y=i.top+p,f-=1}while(f>0&&d(u.pos,a.pos));if(0===f&&d(u.pos,a.pos))return}v.push(i,u),v.push(i,a)}else{var h=a.pos.x,g=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*h,i.massY=i.massY+a.mass*g;var m=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;h>w&&(m+=1,x=w,w=i.right),g>E&&(m+=2,b=E,E=i.bottom);var L=r(i,m);L?v.push(L,a):(L=t(),L.left=x,L.top=b,L.right=w,L.bottom=E,L.body=a,o(i,m,L))}}}n=n||{},n.gravity="number"==typeof n.gravity?n.gravity:-1,n.theta="number"==typeof n.theta?n.theta:.8;var s=e("ngraph.random").random(1984),f=e("./node"),c=e("./insertStack"),d=e("./isSamePosition"),l=n.gravity,p=[],v=new c,h=n.theta,g=[],m=0,y=t();return{insertBodies:a,getRoot:function(){return y},updateBodyForce:i,options:function(e){return e?("number"==typeof e.gravity&&(l=e.gravity),"number"==typeof e.theta&&(h=e.theta),this):{gravity:l,theta:h}}}}},{"./insertStack":27,"./isSamePosition":28,"./node":29,"ngraph.random":30}],27:[function(e,n,t){function r(){this.stack=[],this.popIdx=0}function o(e,n){this.node=e,this.body=n}n.exports=r,r.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new o(e,n),++this.popIdx},pop:function(){if(this.popIdx>0)return this.stack[--this.popIdx]},reset:function(){this.popIdx=0}}},{}],28:[function(e,n,t){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return t<1e-8&&r<1e-8}},{}],29:[function(e,n,t){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],30:[function(e,n,t){function r(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function o(e,n){var t=n||r();if("function"!=typeof t.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var r,o,i;for(r=e.length-1;r>0;--r)o=t.next(r+1),i=e[o],e[o]=e[r],e[r]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,r,o;for(n=e.length-1;n>0;--n)r=t.next(n+1),o=e[r],e[r]=e[n],e[n]=o;return e}}}n.exports={random:r,randomIterator:o}},{}],31:[function(e,n,t){function r(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=r},{}],32:[function(e,n,t){function r(e,n){var t=o(e);if(void 0===n)return t;for(var r=Object.keys(n),i=0;iv&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},j=function(e){p=!1,o.off("touchmove",P),o.off("touchend",j),o.off("touchcancel",j),c=null,r&&r(e)},A=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,o.on("touchmove",P),o.on("touchend",j),o.on("touchcancel",j))},_=function(e){return 1===e.touches.length?A(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=k(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),o.off("mousemove",w),o.off("mouseup",E),o.off("touchmove",P),o.off("touchend",j),o.off("touchcancel",j),N(null)}}}n.exports=r;var o=e("../Utils/documentEvents.js"),i=e("../Utils/browserInfo.js"),a=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":43,"../Utils/documentEvents.js":44,"../Utils/findElementPosition.js":45}],40:[function(e,n,t){function r(e,n){var t=o(n),r=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){r=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(r);var o=i[e.id];return o&&o.onStart&&o.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(r),r=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(r){var t=i[r.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=r;var o=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":61}],41:[function(e,n,t){function r(e,n){function t(e){return d[e]}n=o(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var r=i(n.seed),u=new a(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(e){return{x:r.next(n.maxX),y:r.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},h=function(e){for(var n=0;n=0:"boolean"!=typeof q||q}function r(){G=G||window.document.body,O=O||i(e,{springLength:80,springCoeff:2e-4}),F=F||a(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(F.inputManager||s)(e,F)}function l(){F.beginRender(),n.renderLinks&&F.renderLinks(),F.renderNodes(),F.endRender()}function p(){return X=O.step()&&!V,l(),!X}function v(e){R||(R=void 0!==e?f(function(){if(e-=1,e<0){var n=!1;return n}return p()},M):f(p,M))}function h(){W||(X=!1,R.restart())}function g(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;e0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,h(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):r=e),t},getSvgRoot:function(){return t}};return i(b),b}n.exports=r;var o=e("simplesvg"),i=e("ngraph.events"),a=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":38,"ngraph.events":9,simplesvg:32}],54:[function(e,n,t){function r(e){e=c(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,r,d,l,p,v,h,g=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=i(),N=a(),k=function(e){return u()},P=function(e){return s(3014898687)},j=function(){L.updateTransform(y),N.updateTransform(y)},A=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),r&&r.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),N&&N.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){if("function"==typeof e)return k=e,this},link:function(e){if("function"==typeof e)return P=e,this},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:o,beginRender:function(){},endRender:function(){m>0&&L.render(),g>0&&N.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,j()},addLink:function(e,n){var t=m++,r=P(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=g++,r=k(e);return r.id=t,r.position=n,r.node=e,N.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],j()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,j(),I(this),y[0]},resetScale:function(){return A(),r&&(_(),j()),this},updateSize:_,init:function(o){var i={};if(e.preserveDrawingBuffer&&(i.preserveDrawingBuffer=!0),n=o,_(),A(),n.appendChild(t),r=t.getContext("experimental-webgl",i),!r){var a="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(a),a}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var u=e.clearColorValue;r.clearColor(u.r,u.g,u.b,u.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}L.load(r),L.updateSize(d/2,l/2),N.load(r),N.updateSize(d/2,l/2),j(),"function"==typeof h&&h(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(t0&&(g-=1);var n=b[e.id];delete b[e.id],N.removeNode(n);var t=n.id;if(te.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;o=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*g,r.row*g,g,g),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/h<<0,i=r%h;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*g,i=n.row*g;r.drawImage(t,e.col*g,e.row*g,g,g,o,i,g,g),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,h=Math.sqrt(e||1024)<<0,g=h,m=1,y={},x=0,w=[],b=[];if(!o(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:r,getCoordinates:a,load:u};return E}function o(e){return 0===(e&e-1)}var i=e("./texture.js");n.exports=r},{"./texture.js":56}],59:[function(e,n,t){function r(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=r},{}],60:[function(e,n,t){function r(){function e(e,n){e.nativeObject&&g.deleteTexture(e.nativeObject);var t=g.createTexture();g.activeTexture(g["TEXTURE"+n]),g.bindTexture(g.TEXTURE_2D,t),g.texImage2D(g.TEXTURE_2D,0,g.RGBA,g.RGBA,g.UNSIGNED_BYTE,e.canvas),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MAG_FILTER,g.LINEAR),g.texParameteri(g.TEXTURE_2D,g.TEXTURE_MIN_FILTER,g.LINEAR_MIPMAP_NEAREST),g.generateMipmap(g.TEXTURE_2D),g.uniform1i(x["sampler"+n],n),e.nativeObject=t}function n(){if(v.isDirty){var n,t=v.getTextures();for(n=0;n0&&(A-=1),e.id0&&(e.src&&v.remove(e.src),y.copyArrayPart(_,e.id*N,A*N,N))}function c(e,n){n._offset=e._offset}function d(e){L=!0,E=e}function l(e,n){w=e,b=n,L=!0}function p(){g.useProgram(h),g.bindBuffer(g.ARRAY_BUFFER,m),g.bufferData(g.ARRAY_BUFFER,_,g.DYNAMIC_DRAW),L&&(L=!1,g.uniformMatrix4fv(x.transform,!1,E),g.uniform2f(x.screenSize,w,b)),g.vertexAttribPointer(x.vertexPos,2,g.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),g.vertexAttribPointer(x.customAttributes,1,g.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),n(),g.drawArrays(g.TRIANGLES,0,6*A)}var v,h,g,m,y,x,w,b,E,L,N=18,k=o(),P=i(),j=1024,A=0,_=new Float32Array(64);return{load:t,position:r,createNode:s,removeNode:f,replaceProperties:c,updateTransform:d,updateSize:l,render:p}}function o(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function i(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var a=e("./webglAtlas.js"),u=e("./webgl.js");n.exports=r},{"./webgl.js":57,"./webglAtlas.js":58}],61:[function(e,n,t){function r(e){function n(){x=null}function t(e){x=e}function r(e){return"function"==typeof e&&P.push(e),A}function i(e){return"function"==typeof e&&k.push(e),A}function a(e){return"function"==typeof e&&N.push(e),A}function u(e){return"function"==typeof e&&L.push(e),A}function s(e){return"function"==typeof e&&E.push(e),A}function f(e){return"function"==typeof e&&b.push(e),A}function c(e){return"function"==typeof e&&w.push(e),A}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-og.byteLength){var e=new ArrayBuffer(2*g.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,g=e}};return{load:function(a){n=a,r=o(a),e=r.createProgram(v,p),n.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),h+=1,a=e.id},removeLink:function(e){h>0&&(h-=1),e.id0&&r.copyArrayPart(y,e.id*d,h*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,g,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*h),a=h-1},bringToFront:function(e){a>e.id&&r.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":57}],64:[function(e,n,t){function r(){function e(){if((P+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(k),N=n,k=t,L=e}}function n(e){d=e,v=o(e),c=v.createProgram(E,b),d.useProgram(c),p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]), -d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;N[t*x]=n.x,N[t*x+1]=-n.y,N[t*x+2]=e.size,k[t*x+3]=e.color}function r(e){y=!0,m=e}function i(e,n){h=e,g=n,y=!0}function a(e){P>0&&(P-=1),e.id0&&v.copyArrayPart(k,e.id*x,P*x,x)}function u(){e(),P+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,h,g)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,P)}var c,d,l,p,v,h,g,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),N=new Float32Array(L),k=new Uint32Array(L),P=0;return{load:n,position:t,updateTransform:r,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":57}],65:[function(e,n,t){function r(e,n){return{size:"number"==typeof e?e:10,color:o(n)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":55}],66:[function(e,n,t){n.exports="0.10.1"},{}]},{},[1])(1)}); \ No newline at end of file +n[i]);a?a.push(t):a=n[i]=[t]}}}n.exports=r;var u=/{{(.+?)}}/},{}],35:[function(e,n,t){function r(){return"undefined"==typeof DOMParser?{parseFromString:o}:new DOMParser}function o(){throw new Error("DOMParser is not supported by this platform. Please open issue here https://github.com/anvaka/simplesvg")}n.exports=r()},{}],36:[function(e,n,t){function r(){return{betweennessCentrality:o,degreeCentrality:i}}function o(e){var n=u.betweenness(e);return a(n)}function i(e,n){var t=u.degree(e,n);return a(t)}function a(e){function n(n,t){return e[t]-e[n]}function t(n){return{key:n,value:e[n]}}return Object.keys(e).sort(n).map(t)}var u=e("ngraph.centrality");n.exports=r},{"ngraph.centrality":4}],37:[function(e,n,t){function r(){return{density:function(e,n){var t=e.getNodesCount();return 0===t?NaN:n?e.getLinksCount()/(t*(t-1)):2*e.getLinksCount()/(t*(t-1))}}}n.exports=r},{}],38:[function(e,n,t){function r(e,n){function t(e,t){var i;if(t){var a=n.getNodeUI(e.id);i=o(a),"function"==typeof t.onStart&&i.onStart(t.onStart),"function"==typeof t.onDrag&&i.onDrag(t.onDrag),"function"==typeof t.onStop&&i.onStop(t.onStop),r[e.id]=i}else(i=r[e.id])&&(i.release(),delete r[e.id])}var r={};return{bindDragNDrop:t}}n.exports=r;var o=e("./dragndrop.js")},{"./dragndrop.js":39}],39:[function(e,n,t){function r(e){var n,t,r,u,s,f,c,d=0,l=0,p=!1,v=0,h=function(e){var n=0,t=0;return e=e||window.event,e.pageX||e.pageY?(n=e.pageX,t=e.pageY):(e.clientX||e.clientY)&&(n=e.clientX+window.document.body.scrollLeft+window.document.documentElement.scrollLeft,t=e.clientY+window.document.body.scrollTop+window.document.documentElement.scrollTop),[n,t]},g=function(e,n,r){t&&t(e,{x:n-d,y:r-l}),d=n,l=r},m=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},y=function(e){e.preventDefault&&e.preventDefault()},x=function(e){return m(e),!1},w=function(e){e=e||window.event,g(e,e.clientX,e.clientY)},b=function(e){if(e=e||window.event,p)return m(e),!1;var t=1===e.button&&null!==window.event||0===e.button;return t?(d=e.clientX,l=e.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),o.on("mousemove",w),o.on("mouseup",E),m(e),s=window.document.onselectstart,f=window.document.ondragstart,window.document.onselectstart=x,c.ondragstart=x,!1):void 0},E=function(e){e=e||window.event,o.off("mousemove",w),o.off("mouseup",E),window.document.onselectstart=s,c.ondragstart=f,c=null,r&&r(e)},L=function(n){if("function"==typeof u){n=n||window.event,n.preventDefault&&n.preventDefault(),n.returnValue=!1;var t,r=h(n),o=a(e),i={x:r[0]-o[0],y:r[1]-o[1]};t=n.wheelDelta?n.wheelDelta/360:n.detail/-9,u(n,t,i)}},N=function(n){!u&&n?"webkit"===i.browser?e.addEventListener("mousewheel",L,!1):e.addEventListener("DOMMouseScroll",L,!1):u&&!n&&("webkit"===i.browser?e.removeEventListener("mousewheel",L,!1):e.removeEventListener("DOMMouseScroll",L,!1)),u=n},k=function(e,n){return(e.clientX-n.clientX)*(e.clientX-n.clientX)+(e.clientY-n.clientY)*(e.clientY-n.clientY)},P=function(e){if(1===e.touches.length){m(e);var n=e.touches[0];g(e,n.clientX,n.clientY)}else if(2===e.touches.length){var t=k(e.touches[0],e.touches[1]),r=0;tv&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},j=function(e){p=!1,o.off("touchmove",P),o.off("touchend",j),o.off("touchcancel",j),c=null,r&&r(e)},A=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,o.on("touchmove",P),o.on("touchend",j),o.on("touchcancel",j))},_=function(e){return 1===e.touches.length?A(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=k(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),o.off("mousemove",w),o.off("mouseup",E),o.off("touchmove",P),o.off("touchend",j),o.off("touchcancel",j),N(null)}}}n.exports=r;var o=e("../Utils/documentEvents.js"),i=e("../Utils/browserInfo.js"),a=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":43,"../Utils/documentEvents.js":44,"../Utils/findElementPosition.js":45}],40:[function(e,n,t){function r(e,n){var t=o(n),r=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){r=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(r);var o=i[e.id];return o&&o.onStart&&o.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(r),r=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(r){var t=i[r.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=r;var o=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":61}],41:[function(e,n,t){function r(e,n){function t(e){return d[e]}n=o(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var r=i(n.seed),u=new a(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(e){return{x:r.next(n.maxX),y:r.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},h=function(e){for(var n=0;n=0:"boolean"!=typeof q||q}function r(){G=G||window.document.body,O=O||i(e,{springLength:80,springCoeff:2e-4}),F=F||a(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(F.inputManager||s)(e,F)}function l(){F.beginRender(),n.renderLinks&&F.renderLinks(),F.renderNodes(),F.endRender()}function p(){return X=O.step()&&!V,l(),!X}function v(e){R||(R=void 0!==e?f(function(){if(e-=1,e<0){var n=!1;return n}return p()},M):f(p,M))}function h(){W||(X=!1,R.restart())}function g(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;e0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,h(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):r=e),t},getSvgRoot:function(){return t}};return i(b),b}n.exports=r;var o=e("simplesvg"),i=e("ngraph.events"),a=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":38,"ngraph.events":9,simplesvg:32}],54:[function(e,n,t){function r(e){e=c(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,r,d,l,p,v,h,g=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=i(),N=a(),k=function(e){return u()},P=function(e){return s(3014898687)},j=function(){L.updateTransform(y),N.updateTransform(y)},A=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),r&&r.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),N&&N.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){if("function"==typeof e)return k=e,this},link:function(e){if("function"==typeof e)return P=e,this},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:o,beginRender:function(){},endRender:function(){m>0&&L.render(),g>0&&N.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,j()},addLink:function(e,n){var t=m++,r=P(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=g++,r=k(e);return r.id=t,r.position=n,r.node=e,N.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],j()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,j(),I(this),y[0]},resetScale:function(){return A(),r&&(_(),j()),this},updateSize:_,init:function(o){var i={};if(e.preserveDrawingBuffer&&(i.preserveDrawingBuffer=!0),n=o,_(),A(),n.appendChild(t),r=t.getContext("experimental-webgl",i),!r){var a="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(a),a}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var u=e.clearColorValue;r.clearColor(u.r,u.g,u.b,u.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}L.load(r),L.updateSize(d/2,l/2),N.load(r),N.updateSize(d/2,l/2),j(),"function"==typeof h&&h(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(t0&&(g-=1);var n=b[e.id];delete b[e.id],N.removeNode(n);var t=n.id;if(te.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;o=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*g,r.row*g,g,g),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/h<<0,i=r%h;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*g,i=n.row*g;r.drawImage(t,e.col*g,e.row*g,g,g,o,i,g,g),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,h=Math.sqrt(e||1024)<<0,g=h,m=1,y={},x=0,w=[],b=[];if(!o(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:r,getCoordinates:a,load:u};return E}function o(e){return 0===(e&e-1)}var i=e("./texture.js");n.exports=r},{"./texture.js":56}],59:[function(e,n,t){function r(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=r},{}],60:[function(e,n,t){function r(e){function n(e,n){e.nativeObject&&m.deleteTexture(e.nativeObject);var t=m.createTexture();m.activeTexture(m["TEXTURE"+n]),m.bindTexture(m.TEXTURE_2D,t),m.texImage2D(m.TEXTURE_2D,0,m.RGBA,m.RGBA,m.UNSIGNED_BYTE,e.canvas),m.texParameteri(m.TEXTURE_2D,m.TEXTURE_MAG_FILTER,m.LINEAR),m.texParameteri(m.TEXTURE_2D,m.TEXTURE_MIN_FILTER,m.LINEAR_MIPMAP_NEAREST),m.generateMipmap(m.TEXTURE_2D),m.uniform1i(w["sampler"+n],n),e.nativeObject=t}function t(){if(h.isDirty){var e,t=h.getTextures();for(e=0;e0&&(A-=1),e.id0&&(e.src&&h.remove(e.src),x.copyArrayPart(_,e.id*k,A*k,k))}function d(e,n){n._offset=e._offset}function l(e){N=!0,L=e}function p(e,n){b=e,E=n,N=!0}function v(){m.useProgram(g),m.bindBuffer(m.ARRAY_BUFFER,y),m.bufferData(m.ARRAY_BUFFER,_,m.DYNAMIC_DRAW),N&&(N=!1,m.uniformMatrix4fv(w.transform,!1,L),m.uniform2f(w.screenSize,b,E)),m.vertexAttribPointer(w.vertexPos,2,m.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),m.vertexAttribPointer(w.customAttributes,1,m.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),t(),m.drawArrays(m.TRIANGLES,0,6*A)}var h,g,m,y,x,w,b,E,L,N,k=18,P=o(),j=i(),e=e||1024,A=0,_=new Float32Array(64);return{load:r,position:s,createNode:f,removeNode:c,replaceProperties:d,updateTransform:l,updateSize:p,render:v}}function o(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function i(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var a=e("./webglAtlas.js"),u=e("./webgl.js");n.exports=r},{"./webgl.js":57,"./webglAtlas.js":58}],61:[function(e,n,t){function r(e){function n(){x=null}function t(e){x=e}function r(e){return"function"==typeof e&&P.push(e),A}function i(e){return"function"==typeof e&&k.push(e),A}function a(e){return"function"==typeof e&&N.push(e),A}function u(e){return"function"==typeof e&&L.push(e),A}function s(e){return"function"==typeof e&&E.push(e),A}function f(e){return"function"==typeof e&&b.push(e),A}function c(e){return"function"==typeof e&&w.push(e),A}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-og.byteLength){var e=new ArrayBuffer(2*g.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,g=e}};return{load:function(a){n=a,r=o(a),e=r.createProgram(v,p),n.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),h+=1,a=e.id},removeLink:function(e){h>0&&(h-=1),e.id0&&r.copyArrayPart(y,e.id*d,h*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,g,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*h),a=h-1},bringToFront:function(e){a>e.id&&r.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":57}],64:[function(e,n,t){function r(){function e(){if((P+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(k),N=n,k=t,L=e}}function n(e){d=e,v=o(e),c=v.createProgram(E,b),d.useProgram(c), +p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;N[t*x]=n.x,N[t*x+1]=-n.y,N[t*x+2]=e.size,k[t*x+3]=e.color}function r(e){y=!0,m=e}function i(e,n){h=e,g=n,y=!0}function a(e){P>0&&(P-=1),e.id0&&v.copyArrayPart(k,e.id*x,P*x,x)}function u(){e(),P+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,h,g)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,P)}var c,d,l,p,v,h,g,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),N=new Float32Array(L),k=new Uint32Array(L),P=0;return{load:n,position:t,updateTransform:r,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":57}],65:[function(e,n,t){function r(e,n){return{size:"number"==typeof e?e:10,color:o(n)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":55}],66:[function(e,n,t){n.exports="0.10.1"},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..77cb225 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,4582 @@ +{ + "name": "vivagraphjs", + "version": "0.11.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "Base64": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/Base64/-/Base64-0.2.1.tgz", + "integrity": "sha1-ujpCMHCOGGcFBl5mur3Uw1z2ACg=", + "dev": true + }, + "JSONStream": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.8.4.tgz", + "integrity": "sha1-kWV9/m/4V0gwZhMrRhi2Lo9Ih70=", + "dev": true, + "requires": { + "jsonparse": "0.0.5", + "through": ">=2.2.7 <3" + } + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "dev": true + }, + "acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dev": true, + "requires": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + }, + "dependencies": { + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + } + } + }, + "acorn-walk": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.0.0.tgz", + "integrity": "sha512-7Bv1We7ZGuU79zZbb6rRqcpxo3OY+zrdtloZWoyD8fmGX+FeXRjE+iuGkZjSXLVovLzrsvMGMy0EkwA0E0umxg==", + "dev": true + }, + "add-event-listener": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/add-event-listener/-/add-event-listener-0.0.1.tgz", + "integrity": "sha1-p2Ip68ZMiu+uIEoWJzovJVq+otA=" + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true + }, + "array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "assert": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.3.0.tgz", + "integrity": "sha1-A5OaYiWCqBLMICMgoLmlbJuBWEk=", + "dev": true, + "requires": { + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "astw": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/astw/-/astw-2.2.0.tgz", + "integrity": "sha1-e9QXhNMkk5h66yOba04cV6hzuRc=", + "dev": true, + "requires": { + "acorn": "^4.0.3" + } + }, + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "base64-js": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", + "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=", + "dev": true + }, + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", + "dev": true + }, + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "dev": true, + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + } + } + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browser-pack": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-3.2.0.tgz", + "integrity": "sha1-+qHLxBSHsazEdH43PhFIrf/Q4tk=", + "dev": true, + "requires": { + "JSONStream": "~0.8.4", + "combine-source-map": "~0.3.0", + "concat-stream": "~1.4.1", + "defined": "~0.0.0", + "through2": "~0.5.1", + "umd": "^2.1.0" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "through2": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", + "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", + "dev": true, + "requires": { + "readable-stream": "~1.0.17", + "xtend": "~3.0.0" + } + } + } + }, + "browser-resolve": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "dev": true, + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "browserify": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-8.1.3.tgz", + "integrity": "sha1-8zpUmjpsNoIZsHX9z+bfGV4Empo=", + "dev": true, + "requires": { + "JSONStream": "~0.8.3", + "assert": "~1.3.0", + "browser-pack": "^3.2.0", + "browser-resolve": "^1.3.0", + "browserify-zlib": "~0.1.2", + "buffer": "^3.0.0", + "builtins": "~0.0.3", + "commondir": "0.0.1", + "concat-stream": "~1.4.1", + "console-browserify": "^1.1.0", + "constants-browserify": "~0.0.1", + "crypto-browserify": "^3.0.0", + "deep-equal": "~0.2.1", + "defined": "~0.0.0", + "deps-sort": "^1.3.5", + "domain-browser": "~1.1.0", + "duplexer2": "~0.0.2", + "events": "~1.0.0", + "glob": "^4.0.5", + "http-browserify": "^1.4.0", + "https-browserify": "~0.0.0", + "inherits": "~2.0.1", + "insert-module-globals": "^6.2.0", + "isarray": "0.0.1", + "labeled-stream-splicer": "^1.0.0", + "module-deps": "^3.6.3", + "os-browserify": "~0.1.1", + "parents": "^1.0.1", + "path-browserify": "~0.0.0", + "process": "^0.10.0", + "punycode": "~1.2.3", + "querystring-es3": "~0.2.0", + "readable-stream": "^1.0.33-1", + "resolve": "~0.7.1", + "shallow-copy": "0.0.1", + "shasum": "^1.0.0", + "shell-quote": "~0.0.1", + "stream-browserify": "^1.0.0", + "string_decoder": "~0.10.0", + "subarg": "^1.0.0", + "syntax-error": "^1.1.1", + "through2": "^1.0.0", + "timers-browserify": "^1.0.1", + "tty-browserify": "~0.0.0", + "umd": "~2.1.0", + "url": "~0.10.1", + "util": "~0.10.1", + "vm-browserify": "~0.0.1", + "xtend": "^3.0.0" + } + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, + "requires": { + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" + } + }, + "browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", + "dev": true, + "requires": { + "pako": "~0.2.0" + } + }, + "buffer": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz", + "integrity": "sha1-pyyTb3e5a/UvX357RnGAYoVR3vs=", + "dev": true, + "requires": { + "base64-js": "0.0.8", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "buffer-equal": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.2.tgz", + "integrity": "sha1-7Lt5D1aNQAmKYkK1SAXHWAXrk48=", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtins": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-0.0.7.tgz", + "integrity": "sha1-NVIZzWzxjb58Acx/0tznZc/cVJo=", + "dev": true + }, + "bunker": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/bunker/-/bunker-0.1.2.tgz", + "integrity": "sha1-yImSRkqOKm7ehpMDdfkrWAd++Xw=", + "dev": true, + "requires": { + "burrito": ">=0.2.5 <0.3" + } + }, + "burrito": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/burrito/-/burrito-0.2.12.tgz", + "integrity": "sha1-0NbmrIHV6ZeJxvpKzLCwAx6lT2s=", + "dev": true, + "requires": { + "traverse": "~0.5.1", + "uglify-js": "~1.1.1" + }, + "dependencies": { + "traverse": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.5.2.tgz", + "integrity": "sha1-4gPFjV9/DjfbbnTArLkpuwm2HYU=", + "dev": true + }, + "uglify-js": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-1.1.1.tgz", + "integrity": "sha1-7nGpfEzv0GoamyBDfzQRiYKqA1s=", + "dev": true + } + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "dev": true + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "requires": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "charm": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/charm/-/charm-0.1.2.tgz", + "integrity": "sha1-BsIe7RobBq62dVPNxT4jJ0usIpY=", + "dev": true + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + } + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, + "combine-source-map": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.3.0.tgz", + "integrity": "sha1-2edPWT2c1DgHMSy12EbUUe+qnrc=", + "dev": true, + "requires": { + "convert-source-map": "~0.3.0", + "inline-source-map": "~0.3.0", + "source-map": "~0.1.31" + } + }, + "commondir": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-0.0.1.tgz", + "integrity": "sha1-ifAP3NUbUZxXhzP+xWPmptp/W+I=", + "dev": true + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.4.11.tgz", + "integrity": "sha512-X3JMh8+4je3U1cQpG87+f9lXHDrqcb2MVLg9L7o8b1UZ0DzhRrUpdn65ttzu10PpJPPI3MQNkis+oha6TSA9Mw==", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "~1.1.9", + "typedarray": "~0.0.5" + } + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "^0.1.4" + } + }, + "constants-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-0.0.1.tgz", + "integrity": "sha1-kld9tSe6bEzwpFaNhLwDH0QeIfI=", + "dev": true + }, + "convert-source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-0.3.5.tgz", + "integrity": "sha1-8dgClQr33SYxof6+BZZVDIarMZA=", + "dev": true + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "dateformat": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", + "dev": true + }, + "deap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deap/-/deap-1.0.1.tgz", + "integrity": "sha512-k75KYNZMvwAwes2xIPry/QTffXIchjD8QfABvvfTr80P85jv5ZcKqcoDo+vMe71nNnVnXYe8MA28weyqcf/DKw==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "deep-equal": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.2.2.tgz", + "integrity": "sha1-hLdFiW80xoTpjyzg5Cq69Du6AX0=", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "^1.0.2" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "defined": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-0.0.0.tgz", + "integrity": "sha1-817qfXBekzuvE7LwOz+D2SFAOz4=", + "dev": true + }, + "del": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/del/-/del-1.2.1.tgz", + "integrity": "sha1-rtblvNfLcyXfNPVjEl+iZbLBoBQ=", + "dev": true, + "requires": { + "each-async": "^1.0.0", + "globby": "^2.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^3.0.0", + "rimraf": "^2.2.8" + } + }, + "deprecated": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", + "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", + "dev": true + }, + "deps-sort": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-1.3.9.tgz", + "integrity": "sha1-Kd//U+F7Nq7K51MK27v2IsLtGnE=", + "dev": true, + "requires": { + "JSONStream": "^1.0.3", + "shasum": "^1.0.0", + "subarg": "^1.0.0", + "through2": "^1.0.0" + }, + "dependencies": { + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + } + } + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "detective": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", + "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", + "dev": true, + "requires": { + "acorn": "^5.2.1", + "defined": "^1.0.0" + }, + "dependencies": { + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "dev": true + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + } + } + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "difflet": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/difflet/-/difflet-0.2.6.tgz", + "integrity": "sha1-qyOzH1ZJtvqo49KsvTNEZzZcpvo=", + "dev": true, + "requires": { + "charm": "0.1.x", + "deep-is": "0.1.x", + "traverse": "0.6.x" + } + }, + "domain-browser": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", + "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", + "dev": true + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "requires": { + "readable-stream": "~1.1.9" + } + }, + "each-async": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/each-async/-/each-async-1.1.1.tgz", + "integrity": "sha1-3uUim98KtrogEqOV4bhpq/iBNHM=", + "dev": true, + "requires": { + "onetime": "^1.0.0", + "set-immediate-shim": "^1.0.0" + } + }, + "elliptic": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.1.tgz", + "integrity": "sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg==", + "dev": true, + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, + "end-of-stream": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", + "dev": true, + "requires": { + "once": "~1.3.0" + }, + "dependencies": { + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "dev": true, + "requires": { + "wrappy": "1" + } + } + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "events": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/events/-/events-1.0.2.tgz", + "integrity": "sha1-dYSdz+k9EPsFfDAFWv29UdBqjiQ=", + "dev": true + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "dev": true, + "requires": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-index": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", + "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", + "dev": true + }, + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + } + }, + "first-chunk-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", + "dev": true + }, + "flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "gaze": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", + "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", + "dev": true, + "requires": { + "globule": "~0.1.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "gintersect": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/gintersect/-/gintersect-0.1.0.tgz", + "integrity": "sha1-moy2qAt9bpVawzUVSVsSEmJ7GBY=" + }, + "glob": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^2.0.1", + "once": "^1.3.0" + } + }, + "glob-stream": { + "version": "3.1.18", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", + "dev": true, + "requires": { + "glob": "^4.3.1", + "glob2base": "^0.0.12", + "minimatch": "^2.0.1", + "ordered-read-streams": "^0.1.0", + "through2": "^0.6.1", + "unique-stream": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + } + } + }, + "glob-watcher": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", + "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", + "dev": true, + "requires": { + "gaze": "^0.5.1" + } + }, + "glob2base": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", + "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", + "dev": true, + "requires": { + "find-index": "^0.1.1" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "globby": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-2.1.0.tgz", + "integrity": "sha1-npGSvNM/Srak+JTl5+qLcTITxII=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "async": "^1.2.1", + "glob": "^5.0.3", + "object-assign": "^3.0.0" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "globule": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", + "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", + "dev": true, + "requires": { + "glob": "~3.1.21", + "lodash": "~1.0.1", + "minimatch": "~0.2.11" + }, + "dependencies": { + "glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true, + "requires": { + "graceful-fs": "~1.2.0", + "inherits": "1", + "minimatch": "~0.2.11" + } + }, + "graceful-fs": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "dev": true + }, + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + } + } + }, + "glogg": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", + "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } + }, + "graceful-fs": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.12.tgz", + "integrity": "sha512-J55gaCS4iTTJfTXIxSVw3EMQckcqkpdRv3IR7gu6sq0+tbC363Zx6KH/SEwXASK9JRbhyZmVjJEVJIOxYsB3Qg==", + "dev": true, + "requires": { + "natives": "^1.1.3" + } + }, + "gulp": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", + "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", + "dev": true, + "requires": { + "archy": "^1.0.0", + "chalk": "^1.0.0", + "deprecated": "^0.0.1", + "gulp-util": "^3.0.0", + "interpret": "^1.0.0", + "liftoff": "^2.1.0", + "minimist": "^1.1.0", + "orchestrator": "^0.3.0", + "pretty-hrtime": "^1.0.0", + "semver": "^4.1.0", + "tildify": "^1.0.0", + "v8flags": "^2.0.2", + "vinyl-fs": "^0.3.0" + } + }, + "gulp-rename": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.4.0.tgz", + "integrity": "sha512-swzbIGb/arEoFK89tPY58vg3Ok1bw+d35PfUNwWqdo7KM4jkmuGA78JiDNqR+JeZFaeeHnRg9N7aihX3YPmsyg==", + "dev": true + }, + "gulp-run": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/gulp-run/-/gulp-run-1.7.1.tgz", + "integrity": "sha1-4XwKy3wwtuKu7iPAREKpbAys7/o=", + "dev": true, + "requires": { + "gulp-util": "^3.0.0", + "lodash.defaults": "^4.0.1", + "lodash.template": "^4.0.2", + "vinyl": "^0.4.6" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "^0.2.0", + "clone-stats": "^0.0.1" + } + } + } + }, + "gulp-uglify": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-1.5.4.tgz", + "integrity": "sha1-UkeI2HZm0J+dDCH7IXf5ADmmWMk=", + "dev": true, + "requires": { + "deap": "^1.0.0", + "fancy-log": "^1.0.0", + "gulp-util": "^3.0.0", + "isobject": "^2.0.0", + "through2": "^2.0.0", + "uglify-js": "2.6.4", + "uglify-save-license": "^0.4.1", + "vinyl-sourcemaps-apply": "^0.2.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "uglify-js": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.6.4.tgz", + "integrity": "sha1-ZeovswWck5RpLxX+2HwrNsFrmt8=", + "dev": true, + "requires": { + "async": "~0.2.6", + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } + } + } + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "dev": true, + "requires": { + "array-differ": "^1.0.0", + "array-uniq": "^1.0.2", + "beeper": "^1.0.0", + "chalk": "^1.0.0", + "dateformat": "^2.0.0", + "fancy-log": "^1.1.0", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "lodash._reescape": "^3.0.0", + "lodash._reevaluate": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.template": "^3.0.0", + "minimist": "^1.1.0", + "multipipe": "^0.1.2", + "object-assign": "^3.0.0", + "replace-ext": "0.0.1", + "through2": "^2.0.0", + "vinyl": "^0.5.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "^1.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "http-browserify": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/http-browserify/-/http-browserify-1.7.0.tgz", + "integrity": "sha1-M3la3nLfiKz7/TZ3PO/tp2RzWyA=", + "dev": true, + "requires": { + "Base64": "~0.2.0", + "inherits": "~2.0.1" + } + }, + "https-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", + "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=", + "dev": true + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", + "dev": true + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "inline-source-map": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.3.1.tgz", + "integrity": "sha1-pSi1FOaJ/OkNswiehw2S9Sestes=", + "dev": true, + "requires": { + "source-map": "~0.3.0" + }, + "dependencies": { + "source-map": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.3.0.tgz", + "integrity": "sha1-hYb7mloAXltQHiHNGLbyG0V60fk=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "insert-module-globals": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-6.6.3.tgz", + "integrity": "sha1-IGOOKaMPntHKLjqCX7wsulJG3fw=", + "dev": true, + "requires": { + "JSONStream": "^1.0.3", + "combine-source-map": "~0.6.1", + "concat-stream": "~1.4.1", + "is-buffer": "^1.1.0", + "lexical-scope": "^1.2.0", + "process": "~0.11.0", + "through2": "^1.0.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "combine-source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.6.1.tgz", + "integrity": "sha1-m0oJwxYDPXaODxHgKfonMOB5rZY=", + "dev": true, + "requires": { + "convert-source-map": "~1.1.0", + "inline-source-map": "~0.5.0", + "lodash.memoize": "~3.0.3", + "source-map": "~0.4.2" + } + }, + "convert-source-map": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", + "dev": true + }, + "inline-source-map": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.5.0.tgz", + "integrity": "sha1-Skxd2OT7Xps82mDIIt+tyu5m4K8=", + "dev": true, + "requires": { + "source-map": "~0.4.0" + } + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + } + } + }, + "interpret": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", + "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", + "dev": true + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dev": true, + "requires": { + "is-path-inside": "^1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "requires": { + "is-unc-path": "^1.0.0" + } + }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "requires": { + "unc-path-regex": "^0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "json-stable-stringify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", + "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", + "dev": true, + "requires": { + "jsonify": "~0.0.0" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonparse": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz", + "integrity": "sha1-MwVCrT8KZUZlt3jz6y2an6UHrGQ=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "labeled-stream-splicer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-1.0.2.tgz", + "integrity": "sha1-RhUzFTd4SYHo/SZOHzpDTE4N3WU=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "isarray": "~0.0.1", + "stream-splicer": "^1.1.0" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + }, + "lexical-scope": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/lexical-scope/-/lexical-scope-1.2.0.tgz", + "integrity": "sha1-/Ope3HBKSzqHls3KQZw6CvryLfQ=", + "dev": true, + "requires": { + "astw": "^2.0.0" + } + }, + "liftoff": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", + "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", + "dev": true, + "requires": { + "extend": "^3.0.0", + "findup-sync": "^2.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "lodash": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", + "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", + "dev": true + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", + "dev": true + }, + "lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", + "dev": true + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", + "dev": true + }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", + "dev": true + }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "dev": true, + "requires": { + "lodash._root": "^3.0.0" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + }, + "lodash.memoize": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", + "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=", + "dev": true + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "dev": true, + "requires": { + "lodash._basecopy": "^3.0.0", + "lodash._basetostring": "^3.0.0", + "lodash._basevalues": "^3.0.0", + "lodash._isiterateecall": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0", + "lodash.keys": "^3.0.0", + "lodash.restparam": "^3.0.0", + "lodash.templatesettings": "^3.0.0" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0" + } + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true, + "requires": { + "brace-expansion": "^1.0.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "module-deps": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-3.9.1.tgz", + "integrity": "sha1-6nXK+RmQkNJbDVUStaysuW5/h/M=", + "dev": true, + "requires": { + "JSONStream": "^1.0.3", + "browser-resolve": "^1.7.0", + "concat-stream": "~1.4.5", + "defined": "^1.0.0", + "detective": "^4.0.0", + "duplexer2": "0.0.2", + "inherits": "^2.0.1", + "parents": "^1.0.0", + "readable-stream": "^1.1.13", + "resolve": "^1.1.3", + "stream-combiner2": "~1.0.0", + "subarg": "^1.0.0", + "through2": "^1.0.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "resolve": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "dev": true, + "requires": { + "duplexer2": "0.0.2" + } + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "natives": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.6.tgz", + "integrity": "sha512-6+TDFewD4yxY14ptjKaS63GVdtKiES1pTPyxn9Jb0rBqPMZ7VcCiooEhPNsr+mqHtMGxa/5c/HhcC4uPEUw/nA==", + "dev": true + }, + "ngraph.centrality": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/ngraph.centrality/-/ngraph.centrality-0.3.0.tgz", + "integrity": "sha1-jMDsAxnvCjdDV/wQRMFpdbF50J0=" + }, + "ngraph.events": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/ngraph.events/-/ngraph.events-0.0.3.tgz", + "integrity": "sha1-OPVTFvPSB61jH/lPZiLKjywOh9A=" + }, + "ngraph.expose": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/ngraph.expose/-/ngraph.expose-0.0.0.tgz", + "integrity": "sha1-dGw0kDo4SMRdAzsUvGRhnqhf5ao=" + }, + "ngraph.forcelayout": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/ngraph.forcelayout/-/ngraph.forcelayout-0.5.0.tgz", + "integrity": "sha1-UVEcPh20XT1UNtp137HWrwl5FvU=", + "requires": { + "ngraph.events": "0.0.4", + "ngraph.physics.simulator": "^0.3.0" + }, + "dependencies": { + "ngraph.events": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/ngraph.events/-/ngraph.events-0.0.4.tgz", + "integrity": "sha1-css2RIjdD9fwV0WESfajsXpyLZo=" + } + } + }, + "ngraph.fromjson": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/ngraph.fromjson/-/ngraph.fromjson-0.1.9.tgz", + "integrity": "sha1-ZpELZkxp+jxQoc553R391bq0b24=", + "requires": { + "ngraph.graph": "0.0.14" + } + }, + "ngraph.generators": { + "version": "0.0.19", + "resolved": "https://registry.npmjs.org/ngraph.generators/-/ngraph.generators-0.0.19.tgz", + "integrity": "sha1-VSwNCH+UK50NKwxsqarENr76dlk=", + "requires": { + "ngraph.graph": "0.0.14", + "ngraph.random": "0.1.0" + }, + "dependencies": { + "ngraph.random": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ngraph.random/-/ngraph.random-0.1.0.tgz", + "integrity": "sha1-G26Vc1KeCAZ32m/6CYeQ12oJSKk=" + } + } + }, + "ngraph.graph": { + "version": "0.0.14", + "resolved": "https://registry.npmjs.org/ngraph.graph/-/ngraph.graph-0.0.14.tgz", + "integrity": "sha1-1HrJSWfJIKr3aVLYpOczRuHfLbc=", + "requires": { + "ngraph.events": "0.0.3" + } + }, + "ngraph.merge": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/ngraph.merge/-/ngraph.merge-0.0.1.tgz", + "integrity": "sha1-5OgM43WBo8lrF9VF46Q8hUNLkCU=" + }, + "ngraph.physics.primitives": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ngraph.physics.primitives/-/ngraph.physics.primitives-0.0.7.tgz", + "integrity": "sha1-Xcnhebofkubex3SwHNaJFBILeVs=" + }, + "ngraph.physics.simulator": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/ngraph.physics.simulator/-/ngraph.physics.simulator-0.3.0.tgz", + "integrity": "sha1-fKb8PjYXxz4QgFcuqo4E27d+AQI=", + "requires": { + "ngraph.events": "0.0.3", + "ngraph.expose": "0.0.0", + "ngraph.merge": "0.0.1", + "ngraph.physics.primitives": "0.0.7", + "ngraph.quadtreebh": "0.0.4", + "ngraph.random": "0.0.1" + } + }, + "ngraph.quadtreebh": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/ngraph.quadtreebh/-/ngraph.quadtreebh-0.0.4.tgz", + "integrity": "sha1-xwDUTm5K8HttBQAbo5h/9eLc1iw=", + "requires": { + "ngraph.random": "0.0.1" + } + }, + "ngraph.random": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/ngraph.random/-/ngraph.random-0.0.1.tgz", + "integrity": "sha1-wAji67/f+vF+0Q5LvJE+VnFmvPg=" + }, + "ngraph.remove-overlaps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ngraph.remove-overlaps/-/ngraph.remove-overlaps-1.0.0.tgz", + "integrity": "sha1-tMBjVT6kzx/3gWjnt//2JhfA2fQ=", + "dev": true + }, + "ngraph.tojson": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/ngraph.tojson/-/ngraph.tojson-0.1.4.tgz", + "integrity": "sha1-OfAEZYhECt5iLVhzTVideXSgs7w=" + }, + "nopt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-2.2.1.tgz", + "integrity": "sha1-KqCbfRdoSHs7ianFqlIzW/8Lrqc=", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "optimist": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=", + "dev": true, + "requires": { + "wordwrap": "~0.0.2" + } + }, + "orchestrator": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", + "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", + "dev": true, + "requires": { + "end-of-stream": "~0.1.5", + "sequencify": "~0.0.7", + "stream-consume": "~0.1.0" + } + }, + "ordered-read-streams": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", + "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", + "dev": true + }, + "os-browserify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.1.2.tgz", + "integrity": "sha1-ScoCk+CxlZCl9d4Qx/JlphfY/lQ=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", + "dev": true + }, + "parents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", + "dev": true, + "requires": { + "path-platform": "~0.11.15" + } + }, + "parse-asn1": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz", + "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==", + "dev": true, + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } + }, + "parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-platform": { + "version": "0.11.15", + "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", + "dev": true + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "^0.1.0" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, + "pbkdf2": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", + "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, + "process": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/process/-/process-0.10.1.tgz", + "integrity": "sha1-hCRXzFHP7XLcd1r+6vuMYDQ3JyU=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "punycode": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.2.4.tgz", + "integrity": "sha1-VACKyXKux0F13vnLpt9/qdORh0A=", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "readable-wrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/readable-wrap/-/readable-wrap-1.0.0.tgz", + "integrity": "sha1-O1ohHGMeEjA6VJkcgGwX564ga/8=", + "dev": true, + "requires": { + "readable-stream": "^1.1.13-1" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "^1.1.6" + }, + "dependencies": { + "resolve": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "resolve": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.7.4.tgz", + "integrity": "sha1-OVqe+ehz+/4SvRRAi9kbuTYAPWk=", + "dev": true + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "rfile": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rfile/-/rfile-1.0.0.tgz", + "integrity": "sha1-WXCM+Qyh50xUw8/Fw2/bmBBDUmE=", + "dev": true, + "requires": { + "callsite": "~1.0.0", + "resolve": "~0.3.0" + }, + "dependencies": { + "resolve": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.3.1.tgz", + "integrity": "sha1-NMY0R8ZkxwWY0cmxJvxDsqJDEKQ=", + "dev": true + } + } + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "requires": { + "align-text": "^0.1.1" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.5.tgz", + "integrity": "sha512-J9dlskqUXK1OeTOYBEn5s8aMukWMwWfs+rPTn/jn50Ux4MNXVhubL1wu/j2t+H4NVI+cXEcCaYellqaPVGXNqQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "ruglify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ruglify/-/ruglify-1.0.0.tgz", + "integrity": "sha1-3Ikw4qlUSidDAcyZcldMDQmGtnU=", + "dev": true, + "requires": { + "rfile": "~1.0", + "uglify-js": "~2.2" + }, + "dependencies": { + "uglify-js": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.2.5.tgz", + "integrity": "sha1-puAqcNg5eSuXgEiLe4sYTAlcmcc=", + "dev": true, + "requires": { + "optimist": "~0.3.5", + "source-map": "~0.1.7" + } + } + } + }, + "runforcover": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/runforcover/-/runforcover-0.0.2.tgz", + "integrity": "sha1-NE8FfY1F0zrrxsyCIEZ49pxIV8w=", + "dev": true, + "requires": { + "bunker": "0.1.X" + } + }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "dev": true + }, + "sequencify": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", + "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", + "dev": true + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shallow-copy": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", + "integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=", + "dev": true + }, + "shasum": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", + "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", + "dev": true, + "requires": { + "json-stable-stringify": "~0.0.0", + "sha.js": "~2.4.4" + } + }, + "shell-quote": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-0.0.1.tgz", + "integrity": "sha1-GkEZbzwDM8SCMjWT1ohuzxU92YY=", + "dev": true + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "simplesvg": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/simplesvg/-/simplesvg-0.0.10.tgz", + "integrity": "sha1-N9LsGN4sFU3Ztp956K0gvx4eX90=", + "requires": { + "add-event-listener": "0.0.1" + } + }, + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "dev": true + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "stream-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-1.0.0.tgz", + "integrity": "sha1-v5tKv7QrJ011FHnkTg/yZWtvEZM=", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^1.0.27-1" + } + }, + "stream-combiner2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.0.2.tgz", + "integrity": "sha1-unKmtQy/q/qVD8i8h2BL0B62BnE=", + "dev": true, + "requires": { + "duplexer2": "~0.0.2", + "through2": "~0.5.1" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "through2": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", + "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", + "dev": true, + "requires": { + "readable-stream": "~1.0.17", + "xtend": "~3.0.0" + } + } + } + }, + "stream-consume": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", + "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==", + "dev": true + }, + "stream-splicer": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-1.3.2.tgz", + "integrity": "sha1-PARBvhW5v04iYnXm3IOWR0VUZmE=", + "dev": true, + "requires": { + "indexof": "0.0.1", + "inherits": "^2.0.1", + "isarray": "~0.0.1", + "readable-stream": "^1.1.13-1", + "readable-wrap": "^1.0.0", + "through2": "^1.0.0" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", + "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", + "dev": true, + "requires": { + "first-chunk-stream": "^1.0.0", + "is-utf8": "^0.2.0" + } + }, + "subarg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", + "dev": true, + "requires": { + "minimist": "^1.1.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "syntax-error": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", + "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", + "dev": true, + "requires": { + "acorn-node": "^1.2.0" + } + }, + "tap": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/tap/-/tap-0.4.13.tgz", + "integrity": "sha1-OYYTTWdZcn/CIj5hEm7rhyQ6zLw=", + "dev": true, + "requires": { + "buffer-equal": "~0.0.0", + "deep-equal": "~0.0.0", + "difflet": "~0.2.0", + "glob": "~3.2.1", + "inherits": "*", + "mkdirp": "~0.3 || 0.4 || 0.5", + "nopt": "~2", + "runforcover": "~0.0.2", + "slide": "*", + "yamlish": "*" + }, + "dependencies": { + "deep-equal": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.0.0.tgz", + "integrity": "sha1-mWedO70EcVb81FDT0B7rkGhpHoM=", + "dev": true + }, + "glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "dev": true, + "requires": { + "inherits": "2", + "minimatch": "0.3" + } + }, + "minimatch": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "dev": true, + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + } + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-1.1.1.tgz", + "integrity": "sha1-CEfLxESfNAVXTb3M2buEG4OsNUU=", + "dev": true, + "requires": { + "readable-stream": ">=1.1.13-1 <1.2.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + }, + "dependencies": { + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + } + } + }, + "tildify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "dev": true, + "requires": { + "os-homedir": "^1.0.0" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "timers-browserify": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", + "dev": true, + "requires": { + "process": "~0.11.0" + }, + "dependencies": { + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + } + } + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "traverse": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", + "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=", + "dev": true + }, + "tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "uglify-js": { + "version": "2.4.24", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.24.tgz", + "integrity": "sha1-+tV1XB4Vd2WLsG/5q25UjJW+vW4=", + "dev": true, + "requires": { + "async": "~0.2.6", + "source-map": "0.1.34", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.5.4" + }, + "dependencies": { + "source-map": { + "version": "0.1.34", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.34.tgz", + "integrity": "sha1-p8/omux7FoLDsZjQrPtH19CQVms=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "uglify-save-license": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/uglify-save-license/-/uglify-save-license-0.4.1.tgz", + "integrity": "sha1-lXJsF8xv0XHDYX479NjYKqjEzOE=", + "dev": true + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true + }, + "umd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/umd/-/umd-2.1.0.tgz", + "integrity": "sha1-SmMHt2LxfwLSAbX6FU5nM5bCY88=", + "dev": true, + "requires": { + "rfile": "~1.0.0", + "ruglify": "~1.0.0", + "through": "~2.3.4", + "uglify-js": "~2.4.0" + } + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "unique-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", + "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "dev": true, + "requires": { + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true, + "requires": { + "user-home": "^1.1.1" + } + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vinyl-buffer/-/vinyl-buffer-1.0.1.tgz", + "integrity": "sha1-lsGjR5uMU5JULGEgKQE7Wyf4i78=", + "dev": true, + "requires": { + "bl": "^1.2.1", + "through2": "^2.0.3" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + } + } + }, + "vinyl-fs": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", + "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", + "dev": true, + "requires": { + "defaults": "^1.0.0", + "glob-stream": "^3.1.5", + "glob-watcher": "^0.0.6", + "graceful-fs": "^3.0.0", + "mkdirp": "^0.5.0", + "strip-bom": "^1.0.0", + "through2": "^0.6.1", + "vinyl": "^0.4.0" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "^0.2.0", + "clone-stats": "^0.0.1" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + } + } + }, + "vinyl-source-stream": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-1.1.2.tgz", + "integrity": "sha1-YrU6E1YQqJbpjKlr7jqH8Aio54A=", + "dev": true, + "requires": { + "through2": "^2.0.3", + "vinyl": "^0.4.3" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "^0.2.0", + "clone-stats": "^0.0.1" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + } + } + }, + "vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", + "dev": true, + "requires": { + "source-map": "^0.5.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "requires": { + "indexof": "0.0.1" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xtend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", + "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", + "dev": true + }, + "yamlish": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/yamlish/-/yamlish-0.0.7.tgz", + "integrity": "sha1-tK+aHcxjYYhzw9bkUewyE8OaV/s=", + "dev": true + }, + "yargs": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.5.4.tgz", + "integrity": "sha1-2K/49mXpTDS9JZvevRv68N3TU2E=", + "dev": true, + "requires": { + "camelcase": "^1.0.2", + "decamelize": "^1.0.0", + "window-size": "0.1.0", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + } + } + } + } +} From f9225471b34d6e5b3d9e2b5203bc19d8a859678e Mon Sep 17 00:00:00 2001 From: Andriy Kashcha Date: Sun, 27 Oct 2019 14:23:20 -0700 Subject: [PATCH 257/276] 0.12.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 77cb225..4f94ec0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.11.0", + "version": "0.12.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 763d3de..fd9b792 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vivagraphjs", - "version": "0.11.0", + "version": "0.12.0", "description": "Graph Drawing Library", "main": "src/viva", "directories": { From 1468f40ae8c46fdb5f297fda09aa717bface5833 Mon Sep 17 00:00:00 2001 From: Andriy Kashcha Date: Sun, 12 Jul 2020 09:28:58 -0700 Subject: [PATCH 258/276] updated years --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index ce35121..9975ae0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2011 - 2019, Andrei Kashcha +Copyright (c) 2011 - 2020, Andrei Kashcha All rights reserved. Redistribution and use in source and binary forms, with or without From 61a765acecf871d5c4c93494ad2af26b634043ef Mon Sep 17 00:00:00 2001 From: Andriy Kashcha Date: Mon, 7 Dec 2020 20:14:15 -0800 Subject: [PATCH 259/276] dropped youtube YouTube's API no longer available, and the project went away. --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 605e8ba..7e2e304 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,6 @@ Enough talking. Show me the demo! Some examples of library usage in the real projects: * [Amazon Visualization](http://www.yasiv.com/amazon#/Search?q=graph%20drawing&category=Books&lang=US) Shows related products on Amazon.com, uses SVG as graph output -* [YouTube Visualization](http://www.yasiv.com/youtube#/Search?q=write%20in%20c) Shows related videos from YouTube. SVG based. * [Graph Viewer](http://www.yasiv.com/graphs#Bai/rw496) visualization of sparse matrices collection of the University of Florida. WebGL based. * [Vkontakte Visualization](http://www.yasiv.com/vk) friendship visualization of the largest social network in Russia [vk.com](https://vk.com). WebGL based. From bb987115d5f1cc8fca0e7ec11f2df058b3915265 Mon Sep 17 00:00:00 2001 From: Andriy Kashcha Date: Sun, 7 Feb 2021 20:26:38 -0800 Subject: [PATCH 260/276] updated years --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 9975ae0..f0cc9c2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2011 - 2020, Andrei Kashcha +Copyright (c) 2011 - 2021, Andrei Kashcha All rights reserved. Redistribution and use in source and binary forms, with or without From 1aa5cc41e1c8d1c16ff8e8732e6bc7d3b4949ae0 Mon Sep 17 00:00:00 2001 From: Matt Bray Date: Wed, 24 Feb 2021 10:27:58 +0000 Subject: [PATCH 261/276] fix(input): listen to standard wheel event --- src/Input/dragndrop.js | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/src/Input/dragndrop.js b/src/Input/dragndrop.js index abe2af3..087fcaf 100644 --- a/src/Input/dragndrop.js +++ b/src/Input/dragndrop.js @@ -130,7 +130,7 @@ function dragndrop(element) { } e.returnValue = false; - var delta, + var delta = e.deltaY, mousePos = getMousePos(e), elementOffset = findElementPosition(element), relMousePos = { @@ -138,29 +138,15 @@ function dragndrop(element) { y: mousePos[1] - elementOffset[1] }; - if (e.wheelDelta) { - delta = e.wheelDelta / 360; // Chrome/Safari - } else { - delta = e.detail / -9; // Mozilla - } - scroll(e, delta, relMousePos); }, updateScrollEvents = function (scrollCallback) { if (!scroll && scrollCallback) { // client is interested in scrolling. Start listening to events: - if (browserInfo.browser === 'webkit') { - element.addEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari - } else { - element.addEventListener('DOMMouseScroll', handleMouseWheel, false); // Others - } + element.addEventListener('wheel', handleMouseWheel, false); } else if (scroll && !scrollCallback) { - if (browserInfo.browser === 'webkit') { - element.removeEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari - } else { - element.removeEventListener('DOMMouseScroll', handleMouseWheel, false); // Others - } + element.removeEventListener('wheel', handleMouseWheel, false); } scroll = scrollCallback; From 9b405a1927c53435835571faef432f5ad5aa7935 Mon Sep 17 00:00:00 2001 From: Andriy Kashcha Date: Fri, 26 Feb 2021 20:03:50 -0800 Subject: [PATCH 262/276] updated gulp to the latest version --- gulpfile.js | 13 +- package-lock.json | 11431 ++++++++++++++++++++++++++++++++++++++++---- package.json | 16 +- 3 files changed, 10416 insertions(+), 1044 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 6ddbe83..e8b3157 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,5 +1,4 @@ var gulp = require('gulp'); -var gutil = require('gulp-util'); var buffer = require('vinyl-buffer'); var source = require('vinyl-source-stream'); @@ -11,7 +10,7 @@ var run = require('gulp-run'); gulp.task('clean', clean); gulp.task('build', build); gulp.task('test', test); -gulp.task('release', ['clean', 'build'], test); +gulp.task('release', gulp.series('clean', 'build', test)); gulp.task('default', watch); function watch() { @@ -22,11 +21,11 @@ function clean(cb) { del(['dist'], cb); } -function test() { - new run.Command('npm test').exec(); +function test(cb) { + new run.Command('npm test').exec('', cb); } -function build() { +function build(cb) { var bundler = require('browserify')('./src/viva.js', { standalone: 'Viva' }); @@ -40,7 +39,9 @@ function build() { .pipe(uglify()) .pipe(gulp.dest('./dist/')); + bundle.on('end', cb); + function showError(err) { - gutil.log(gutil.colors.red('Failed to browserify'), gutil.colors.yellow(err.message)); + console.log('Failed to browserify', err.message); } } diff --git a/package-lock.json b/package-lock.json index 4f94ec0..1f62af6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,25 +1,7523 @@ { "name": "vivagraphjs", "version": "0.12.0", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, - "dependencies": { - "Base64": { + "packages": { + "": { + "name": "vivagraphjs", + "version": "0.12.0", + "license": "BSD-3-Clause", + "dependencies": { + "gintersect": "0.1.0", + "ngraph.centrality": "0.3.0", + "ngraph.events": "0.0.3", + "ngraph.forcelayout": "0.5.0", + "ngraph.fromjson": "0.1.9", + "ngraph.generators": "0.0.19", + "ngraph.graph": "0.0.14", + "ngraph.merge": "0.0.1", + "ngraph.random": "0.0.1", + "ngraph.tojson": "0.1.4", + "simplesvg": "0.0.10" + }, + "devDependencies": { + "browserify": "^8.0.3", + "del": "^1.1.1", + "gulp": "^4.0.2", + "gulp-rename": "^2.0.0", + "gulp-run": "^1.7.1", + "gulp-uglify": "^3.0.2", + "ngraph.remove-overlaps": "^1.0.0", + "tap": "^0.4.13", + "vinyl-buffer": "^1.0.1", + "vinyl-source-stream": "^2.0.0" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "node_modules/acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dev": true, + "dependencies": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "node_modules/acorn-node/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-node/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/add-event-listener": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/add-event-listener/-/add-event-listener-0.0.1.tgz", + "integrity": "sha1-p2Ip68ZMiu+uIEoWJzovJVq+otA=" + }, + "node_modules/amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true, + "engines": { + "node": ">=0.4.2" + } + }, + "node_modules/ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "dependencies": { + "ansi-wrap": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true, + "dependencies": { + "ansi-wrap": "0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "node_modules/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/append-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", + "dev": true, + "dependencies": { + "buffer-equal": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/append-buffer/node_modules/buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "node_modules/arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-filter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", + "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", + "dev": true, + "dependencies": { + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", + "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", + "dev": true, + "dependencies": { + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-initial": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", + "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", + "dev": true, + "dependencies": { + "array-slice": "^1.0.0", + "is-number": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-initial/node_modules/is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-last": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", + "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", + "dev": true, + "dependencies": { + "is-number": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-last/node_modules/is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-sort": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", + "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", + "dev": true, + "dependencies": { + "default-compare": "^1.0.0", + "get-value": "^2.0.6", + "kind-of": "^5.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "dependencies": { + "array-uniq": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dev": true, + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/assert": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.3.0.tgz", + "integrity": "sha1-A5OaYiWCqBLMICMgoLmlbJuBWEk=", + "dev": true, + "dependencies": { + "util": "0.10.3" + } + }, + "node_modules/assert/node_modules/inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "node_modules/assert/node_modules/util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "dependencies": { + "inherits": "2.0.1" + } + }, + "node_modules/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/astw": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/astw/-/astw-2.2.0.tgz", + "integrity": "sha1-e9QXhNMkk5h66yOba04cV6hzuRc=", + "dev": true, + "dependencies": { + "acorn": "^4.0.3" + } + }, + "node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "node_modules/async-done": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", + "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.2", + "process-nextick-args": "^2.0.0", + "stream-exhaust": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true + }, + "node_modules/async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", + "dev": true, + "dependencies": { + "async-done": "^1.2.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true, + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", + "dev": true, + "dependencies": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "node_modules/base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "dependencies": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/Base64": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/Base64/-/Base64-0.2.1.tgz", + "integrity": "sha1-ujpCMHCOGGcFBl5mur3Uw1z2ACg=", + "dev": true + }, + "node_modules/base64-js": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", + "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", + "dev": true, + "dependencies": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/bl/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/bl/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/bl/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "node_modules/browser-pack": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-3.2.0.tgz", + "integrity": "sha1-+qHLxBSHsazEdH43PhFIrf/Q4tk=", + "dev": true, + "dependencies": { + "combine-source-map": "~0.3.0", + "concat-stream": "~1.4.1", + "defined": "~0.0.0", + "JSONStream": "~0.8.4", + "through2": "~0.5.1", + "umd": "^2.1.0" + }, + "bin": { + "browser-pack": "bin/cmd.js" + } + }, + "node_modules/browser-pack/node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/browser-pack/node_modules/through2": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", + "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", + "dev": true, + "dependencies": { + "readable-stream": "~1.0.17", + "xtend": "~3.0.0" + } + }, + "node_modules/browser-resolve": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "dev": true, + "dependencies": { + "resolve": "1.1.7" + } + }, + "node_modules/browser-resolve/node_modules/resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "node_modules/browserify": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-8.1.3.tgz", + "integrity": "sha1-8zpUmjpsNoIZsHX9z+bfGV4Empo=", + "dev": true, + "dependencies": { + "assert": "~1.3.0", + "browser-pack": "^3.2.0", + "browser-resolve": "^1.3.0", + "browserify-zlib": "~0.1.2", + "buffer": "^3.0.0", + "builtins": "~0.0.3", + "commondir": "0.0.1", + "concat-stream": "~1.4.1", + "console-browserify": "^1.1.0", + "constants-browserify": "~0.0.1", + "crypto-browserify": "^3.0.0", + "deep-equal": "~0.2.1", + "defined": "~0.0.0", + "deps-sort": "^1.3.5", + "domain-browser": "~1.1.0", + "duplexer2": "~0.0.2", + "events": "~1.0.0", + "glob": "^4.0.5", + "http-browserify": "^1.4.0", + "https-browserify": "~0.0.0", + "inherits": "~2.0.1", + "insert-module-globals": "^6.2.0", + "isarray": "0.0.1", + "JSONStream": "~0.8.3", + "labeled-stream-splicer": "^1.0.0", + "module-deps": "^3.6.3", + "os-browserify": "~0.1.1", + "parents": "^1.0.1", + "path-browserify": "~0.0.0", + "process": "^0.10.0", + "punycode": "~1.2.3", + "querystring-es3": "~0.2.0", + "readable-stream": "^1.0.33-1", + "resolve": "~0.7.1", + "shallow-copy": "0.0.1", + "shasum": "^1.0.0", + "shell-quote": "~0.0.1", + "stream-browserify": "^1.0.0", + "string_decoder": "~0.10.0", + "subarg": "^1.0.0", + "syntax-error": "^1.1.1", + "through2": "^1.0.0", + "timers-browserify": "^1.0.1", + "tty-browserify": "~0.0.0", + "umd": "~2.1.0", + "url": "~0.10.1", + "util": "~0.10.1", + "vm-browserify": "~0.0.1", + "xtend": "^3.0.0" + }, + "bin": { + "browserify": "bin/cmd.js" + } + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "dev": true, + "dependencies": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "node_modules/browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dev": true, + "dependencies": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "node_modules/browserify-sign/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/browserify-sign/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", + "dev": true, + "dependencies": { + "pako": "~0.2.0" + } + }, + "node_modules/buffer": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-3.6.2.tgz", + "integrity": "sha512-c3M77NkHJxS0zx/ErxXhDLr1v3y2MDXPeTJPvLNOaIYJ4ymHBUFQ9EXzt9HYuqAJllMoNb/EZ8hIiulnQFAUuQ==", + "dev": true, + "dependencies": { + "base64-js": "0.0.8", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "node_modules/buffer-equal": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.2.tgz", + "integrity": "sha1-7Lt5D1aNQAmKYkK1SAXHWAXrk48=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "node_modules/buffer/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/builtins": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-0.0.7.tgz", + "integrity": "sha1-NVIZzWzxjb58Acx/0tznZc/cVJo=", + "dev": true + }, + "node_modules/bunker": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/bunker/-/bunker-0.1.2.tgz", + "integrity": "sha1-yImSRkqOKm7ehpMDdfkrWAd++Xw=", + "dev": true, + "dependencies": { + "burrito": ">=0.2.5 <0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/burrito": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/burrito/-/burrito-0.2.12.tgz", + "integrity": "sha1-0NbmrIHV6ZeJxvpKzLCwAx6lT2s=", + "dev": true, + "dependencies": { + "traverse": "~0.5.1", + "uglify-js": "~1.1.1" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/burrito/node_modules/traverse": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.5.2.tgz", + "integrity": "sha1-4gPFjV9/DjfbbnTArLkpuwm2HYU=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/burrito/node_modules/uglify-js": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-1.1.1.tgz", + "integrity": "sha1-7nGpfEzv0GoamyBDfzQRiYKqA1s=", + "dev": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": "*" + } + }, + "node_modules/cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "dependencies": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/charm": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/charm/-/charm-0.1.2.tgz", + "integrity": "sha1-BsIe7RobBq62dVPNxT4jJ0usIpY=", + "dev": true + }, + "node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "deprecated": "Chokidar 2 will break on node v14+. Upgrade to chokidar 3 with 15x less dependencies.", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "dependencies": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "node_modules/clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "node_modules/cloneable-readable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", + "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + } + }, + "node_modules/cloneable-readable/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/cloneable-readable/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/cloneable-readable/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/cloneable-readable/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/collection-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", + "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", + "dev": true, + "dependencies": { + "arr-map": "^2.0.2", + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "dependencies": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/combine-source-map": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.3.0.tgz", + "integrity": "sha1-2edPWT2c1DgHMSy12EbUUe+qnrc=", + "dev": true, + "dependencies": { + "convert-source-map": "~0.3.0", + "inline-source-map": "~0.3.0", + "source-map": "~0.1.31" + } + }, + "node_modules/commondir": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-0.0.1.tgz", + "integrity": "sha1-ifAP3NUbUZxXhzP+xWPmptp/W+I=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/concat-stream": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.4.11.tgz", + "integrity": "sha512-X3JMh8+4je3U1cQpG87+f9lXHDrqcb2MVLg9L7o8b1UZ0DzhRrUpdn65ttzu10PpJPPI3MQNkis+oha6TSA9Mw==", + "dev": true, + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "inherits": "~2.0.1", + "readable-stream": "~1.1.9", + "typedarray": "~0.0.5" + } + }, + "node_modules/console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, + "node_modules/constants-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-0.0.1.tgz", + "integrity": "sha1-kld9tSe6bEzwpFaNhLwDH0QeIfI=", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-0.3.5.tgz", + "integrity": "sha1-8dgClQr33SYxof6+BZZVDIarMZA=", + "dev": true + }, + "node_modules/copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/copy-props": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", + "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", + "dev": true, + "dependencies": { + "each-props": "^1.3.0", + "is-plain-object": "^2.0.1" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "dependencies": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "node_modules/dateformat": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/deep-equal": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.2.2.tgz", + "integrity": "sha1-hLdFiW80xoTpjyzg5Cq69Du6AX0=", + "dev": true + }, + "node_modules/deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "node_modules/default-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", + "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", + "dev": true, + "dependencies": { + "kind-of": "^5.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-resolution": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", + "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defined": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-0.0.0.tgz", + "integrity": "sha1-817qfXBekzuvE7LwOz+D2SFAOz4=", + "dev": true + }, + "node_modules/del": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/del/-/del-1.2.1.tgz", + "integrity": "sha1-rtblvNfLcyXfNPVjEl+iZbLBoBQ=", + "dev": true, + "dependencies": { + "each-async": "^1.0.0", + "globby": "^2.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^3.0.0", + "rimraf": "^2.2.8" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deps-sort": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-1.3.9.tgz", + "integrity": "sha1-Kd//U+F7Nq7K51MK27v2IsLtGnE=", + "dev": true, + "dependencies": { + "JSONStream": "^1.0.3", + "shasum": "^1.0.0", + "subarg": "^1.0.0", + "through2": "^1.0.0" + }, + "bin": { + "deps-sort": "bin/cmd.js" + } + }, + "node_modules/deps-sort/node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true, + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/deps-sort/node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/detective": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", + "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", + "dev": true, + "dependencies": { + "acorn": "^5.2.1", + "defined": "^1.0.0" + } + }, + "node_modules/detective/node_modules/acorn": { + "version": "5.7.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", + "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detective/node_modules/defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/difflet": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/difflet/-/difflet-0.2.6.tgz", + "integrity": "sha1-qyOzH1ZJtvqo49KsvTNEZzZcpvo=", + "dev": true, + "dependencies": { + "charm": "0.1.x", + "deep-is": "0.1.x", + "traverse": "0.6.x" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/domain-browser": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", + "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", + "dev": true, + "engines": { + "node": ">=0.4", + "npm": ">=1.2" + } + }, + "node_modules/duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "dependencies": { + "readable-stream": "~1.1.9" + } + }, + "node_modules/duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/duplexify/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/duplexify/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/each-async": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/each-async/-/each-async-1.1.1.tgz", + "integrity": "sha1-3uUim98KtrogEqOV4bhpq/iBNHM=", + "dev": true, + "dependencies": { + "onetime": "^1.0.0", + "set-immediate-shim": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/each-props": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", + "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.1", + "object.defaults": "^1.1.0" + } + }, + "node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dev": true, + "dependencies": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "dependencies": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "node_modules/es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/events": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/events/-/events-1.0.2.tgz", + "integrity": "sha1-dYSdz+k9EPsFfDAFWv29UdBqjiQ=", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "dependencies": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, + "dependencies": { + "type": "^2.0.0" + } + }, + "node_modules/ext/node_modules/type": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.3.0.tgz", + "integrity": "sha512-rgPIqOdfK/4J9FhiVrZ3cveAjRRo5rsQBAIhnylX874y1DX/kEKSVdLsnuHB6l1KTjHyU01VjiMBHgU2adejyg==", + "dev": true + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "dependencies": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "dev": true, + "dependencies": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/fast-levenshtein": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", + "integrity": "sha1-5qdUzI8V5YmHqpy9J69m/W9OWvk=", + "dev": true + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "dependencies": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "dev": true, + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "node_modules/flush-write-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/flush-write-stream/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/flush-write-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/flush-write-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "dependencies": { + "for-in": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "dependencies": { + "map-cache": "^0.2.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/fs-mkdirp-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/fs-mkdirp-stream/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/fs-mkdirp-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/fs-mkdirp-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/fs-mkdirp-stream/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/fs-mkdirp-stream/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gintersect": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/gintersect/-/gintersect-0.1.0.tgz", + "integrity": "sha1-moy2qAt9bpVawzUVSVsSEmJ7GBY=" + }, + "node_modules/glob": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "dev": true, + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^2.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", + "dev": true, + "dependencies": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/glob-stream/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/glob-stream/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/glob-stream/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/glob-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/glob-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/glob-watcher": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", + "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "normalize-path": "^3.0.0", + "object.defaults": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "dependencies": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/globby": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-2.1.0.tgz", + "integrity": "sha1-npGSvNM/Srak+JTl5+qLcTITxII=", + "dev": true, + "dependencies": { + "array-union": "^1.0.1", + "async": "^1.2.1", + "glob": "^5.0.3", + "object-assign": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/globby/node_modules/glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/glogg": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", + "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", + "dev": true, + "dependencies": { + "sparkles": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "dev": true + }, + "node_modules/gulp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "dev": true, + "dependencies": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + }, + "bin": { + "gulp": "bin/gulp.js" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-cli": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", + "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", + "dev": true, + "dependencies": { + "ansi-colors": "^1.0.1", + "archy": "^1.0.0", + "array-sort": "^1.0.0", + "color-support": "^1.1.3", + "concat-stream": "^1.6.0", + "copy-props": "^2.0.1", + "fancy-log": "^1.3.2", + "gulplog": "^1.0.0", + "interpret": "^1.4.0", + "isobject": "^3.0.1", + "liftoff": "^3.1.0", + "matchdep": "^2.0.0", + "mute-stdout": "^1.0.0", + "pretty-hrtime": "^1.0.0", + "replace-homedir": "^1.0.0", + "semver-greatest-satisfied-range": "^1.1.0", + "v8flags": "^3.2.0", + "yargs": "^7.1.0" + }, + "bin": { + "gulp": "bin/gulp.js" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-cli/node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/gulp-cli/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/gulp-cli/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/gulp-cli/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/gulp-cli/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/gulp-rename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-2.0.0.tgz", + "integrity": "sha512-97Vba4KBzbYmR5VBs9mWmK+HwIf5mj+/zioxfZhOKeXtx5ZjBk57KFlePf5nxq9QsTtFl0ejnHE3zTC9MHXqyQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/gulp-run": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/gulp-run/-/gulp-run-1.7.1.tgz", + "integrity": "sha1-4XwKy3wwtuKu7iPAREKpbAys7/o=", + "dev": true, + "dependencies": { + "gulp-util": "^3.0.0", + "lodash.defaults": "^4.0.1", + "lodash.template": "^4.0.2", + "vinyl": "^0.4.6" + } + }, + "node_modules/gulp-uglify": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.2.tgz", + "integrity": "sha512-gk1dhB74AkV2kzqPMQBLA3jPoIAPd/nlNzP2XMDSG8XZrqnlCiDGAqC+rZOumzFvB5zOphlFh6yr3lgcAb/OOg==", + "dev": true, + "dependencies": { + "array-each": "^1.0.1", + "extend-shallow": "^3.0.2", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "isobject": "^3.0.1", + "make-error-cause": "^1.1.1", + "safe-buffer": "^5.1.2", + "through2": "^2.0.0", + "uglify-js": "^3.0.5", + "vinyl-sourcemaps-apply": "^0.2.0" + } + }, + "node_modules/gulp-uglify/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-uglify/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-uglify/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/gulp-uglify/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/gulp-uglify/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/gulp-uglify/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/gulp-uglify/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/gulp-uglify/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "deprecated": "gulp-util is deprecated - replace it, following the guidelines at https://medium.com/gulpjs/gulp-util-ca3b1f9f9ac5", + "dev": true, + "dependencies": { + "array-differ": "^1.0.0", + "array-uniq": "^1.0.2", + "beeper": "^1.0.0", + "chalk": "^1.0.0", + "dateformat": "^2.0.0", + "fancy-log": "^1.1.0", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "lodash._reescape": "^3.0.0", + "lodash._reevaluate": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.template": "^3.0.0", + "minimist": "^1.1.0", + "multipipe": "^0.1.2", + "object-assign": "^3.0.0", + "replace-ext": "0.0.1", + "through2": "^2.0.0", + "vinyl": "^0.5.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/gulp-util/node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/gulp-util/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/gulp-util/node_modules/lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "dev": true, + "dependencies": { + "lodash._basecopy": "^3.0.0", + "lodash._basetostring": "^3.0.0", + "lodash._basevalues": "^3.0.0", + "lodash._isiterateecall": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0", + "lodash.keys": "^3.0.0", + "lodash.restparam": "^3.0.0", + "lodash.templatesettings": "^3.0.0" + } + }, + "node_modules/gulp-util/node_modules/lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "dev": true, + "dependencies": { + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0" + } + }, + "node_modules/gulp-util/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/gulp-util/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/gulp-util/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/gulp-util/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/gulp-util/node_modules/vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "dependencies": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + }, + "engines": { + "node": ">= 0.9" + } + }, + "node_modules/gulp-util/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "dependencies": { + "glogg": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "dev": true, + "dependencies": { + "sparkles": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "dependencies": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash-base/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/hash-base/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "node_modules/http-browserify": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/http-browserify/-/http-browserify-1.7.0.tgz", + "integrity": "sha1-M3la3nLfiKz7/TZ3PO/tp2RzWyA=", + "dev": true, + "dependencies": { + "Base64": "~0.2.0", + "inherits": "~2.0.1" + } + }, + "node_modules/https-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", + "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=", + "dev": true + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/inline-source-map": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.3.1.tgz", + "integrity": "sha1-pSi1FOaJ/OkNswiehw2S9Sestes=", + "dev": true, + "dependencies": { + "source-map": "~0.3.0" + } + }, + "node_modules/inline-source-map/node_modules/source-map": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.3.0.tgz", + "integrity": "sha1-hYb7mloAXltQHiHNGLbyG0V60fk=", + "dev": true, + "dependencies": { + "amdefine": ">=0.0.4" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/insert-module-globals": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-6.6.3.tgz", + "integrity": "sha1-IGOOKaMPntHKLjqCX7wsulJG3fw=", + "dev": true, + "dependencies": { + "combine-source-map": "~0.6.1", + "concat-stream": "~1.4.1", + "is-buffer": "^1.1.0", + "JSONStream": "^1.0.3", + "lexical-scope": "^1.2.0", + "process": "~0.11.0", + "through2": "^1.0.0", + "xtend": "^4.0.0" + }, + "bin": { + "insert-module-globals": "bin/cmd.js" + } + }, + "node_modules/insert-module-globals/node_modules/combine-source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.6.1.tgz", + "integrity": "sha1-m0oJwxYDPXaODxHgKfonMOB5rZY=", + "dev": true, + "dependencies": { + "convert-source-map": "~1.1.0", + "inline-source-map": "~0.5.0", + "lodash.memoize": "~3.0.3", + "source-map": "~0.4.2" + } + }, + "node_modules/insert-module-globals/node_modules/convert-source-map": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", + "dev": true + }, + "node_modules/insert-module-globals/node_modules/inline-source-map": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.5.0.tgz", + "integrity": "sha1-Skxd2OT7Xps82mDIIt+tyu5m4K8=", + "dev": true, + "dependencies": { + "source-map": "~0.4.0" + } + }, + "node_modules/insert-module-globals/node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true, + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/insert-module-globals/node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/insert-module-globals/node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/insert-module-globals/node_modules/source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "dependencies": { + "amdefine": ">=0.0.4" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/insert-module-globals/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "dependencies": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/is-core-module": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", + "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-descriptor/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dev": true, + "dependencies": { + "is-path-inside": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "dependencies": { + "path-is-inside": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "dependencies": { + "is-unc-path": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "dependencies": { + "unc-path-regex": "^0.1.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "node_modules/is-valid-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/json-stable-stringify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", + "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", + "dev": true, + "dependencies": { + "jsonify": "~0.0.0" + } + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "node_modules/jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/jsonparse": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz", + "integrity": "sha1-MwVCrT8KZUZlt3jz6y2an6UHrGQ=", + "dev": true, + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/JSONStream": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.8.4.tgz", + "integrity": "sha1-kWV9/m/4V0gwZhMrRhi2Lo9Ih70=", + "dev": true, + "dependencies": { + "jsonparse": "0.0.5", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "index.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/just-debounce": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.1.0.tgz", + "integrity": "sha512-qpcRocdkUmf+UTNBYx5w6dexX5J31AKK1OmPwH630a83DdVVUIngk55RSAiIGpQyoH0dlr872VHfPjnQnK1qDQ==", + "dev": true + }, + "node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/labeled-stream-splicer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-1.0.2.tgz", + "integrity": "sha1-RhUzFTd4SYHo/SZOHzpDTE4N3WU=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "isarray": "~0.0.1", + "stream-splicer": "^1.1.0" + } + }, + "node_modules/last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", + "dev": true, + "dependencies": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/lazystream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/lazystream/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/lazystream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/lazystream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "dependencies": { + "invert-kv": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", + "dev": true, + "dependencies": { + "flush-write-stream": "^1.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/lexical-scope": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/lexical-scope/-/lexical-scope-1.2.0.tgz", + "integrity": "sha1-/Ope3HBKSzqHls3KQZw6CvryLfQ=", + "dev": true, + "dependencies": { + "astw": "^2.0.0" + } + }, + "node_modules/liftoff": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", + "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", + "dev": true, + "dependencies": { + "extend": "^3.0.0", + "findup-sync": "^3.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/liftoff/node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "node_modules/lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", + "dev": true + }, + "node_modules/lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", + "dev": true + }, + "node_modules/lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "node_modules/lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "node_modules/lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", + "dev": true + }, + "node_modules/lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", + "dev": true + }, + "node_modules/lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "node_modules/lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", + "dev": true + }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", + "dev": true + }, + "node_modules/lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "dev": true, + "dependencies": { + "lodash._root": "^3.0.0" + } + }, + "node_modules/lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "node_modules/lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "node_modules/lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "dependencies": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + }, + "node_modules/lodash.memoize": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", + "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=", + "dev": true + }, + "node_modules/lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "node_modules/lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "dev": true, + "dependencies": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "node_modules/lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "dev": true, + "dependencies": { + "lodash._reinterpolate": "^3.0.0" + } + }, + "node_modules/lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/make-error-cause": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", + "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=", + "dev": true, + "dependencies": { + "make-error": "^1.2.0" + } + }, + "node_modules/make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/make-iterator/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "dependencies": { + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/matchdep": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", + "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", + "dev": true, + "dependencies": { + "findup-sync": "^2.0.0", + "micromatch": "^3.0.4", + "resolve": "^1.4.0", + "stack-trace": "0.0.10" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/matchdep/node_modules/findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/matchdep/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/matchdep/node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "node_modules/minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "deprecated": "Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue", + "dev": true, + "dependencies": { + "brace-expansion": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node_modules/mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "dependencies": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mixin-deep/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/module-deps": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-3.9.1.tgz", + "integrity": "sha1-6nXK+RmQkNJbDVUStaysuW5/h/M=", + "dev": true, + "dependencies": { + "browser-resolve": "^1.7.0", + "concat-stream": "~1.4.5", + "defined": "^1.0.0", + "detective": "^4.0.0", + "duplexer2": "0.0.2", + "inherits": "^2.0.1", + "JSONStream": "^1.0.3", + "parents": "^1.0.0", + "readable-stream": "^1.1.13", + "resolve": "^1.1.3", + "stream-combiner2": "~1.0.0", + "subarg": "^1.0.0", + "through2": "^1.0.0", + "xtend": "^4.0.0" + }, + "bin": { + "module-deps": "bin/cmd.js" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/module-deps/node_modules/defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "node_modules/module-deps/node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true, + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/module-deps/node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/module-deps/node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/module-deps/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "dev": true, + "dependencies": { + "duplexer2": "0.0.2" + } + }, + "node_modules/mute-stdout": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", + "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", + "dev": true, + "optional": true + }, + "node_modules/nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanomatch/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanomatch/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanomatch/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "node_modules/ngraph.centrality": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/ngraph.centrality/-/ngraph.centrality-0.3.0.tgz", + "integrity": "sha1-jMDsAxnvCjdDV/wQRMFpdbF50J0=" + }, + "node_modules/ngraph.events": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/ngraph.events/-/ngraph.events-0.0.3.tgz", + "integrity": "sha1-OPVTFvPSB61jH/lPZiLKjywOh9A=" + }, + "node_modules/ngraph.expose": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/ngraph.expose/-/ngraph.expose-0.0.0.tgz", + "integrity": "sha1-dGw0kDo4SMRdAzsUvGRhnqhf5ao=" + }, + "node_modules/ngraph.forcelayout": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/ngraph.forcelayout/-/ngraph.forcelayout-0.5.0.tgz", + "integrity": "sha1-UVEcPh20XT1UNtp137HWrwl5FvU=", + "dependencies": { + "ngraph.events": "0.0.4", + "ngraph.physics.simulator": "^0.3.0" + } + }, + "node_modules/ngraph.forcelayout/node_modules/ngraph.events": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/ngraph.events/-/ngraph.events-0.0.4.tgz", + "integrity": "sha1-css2RIjdD9fwV0WESfajsXpyLZo=" + }, + "node_modules/ngraph.fromjson": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/ngraph.fromjson/-/ngraph.fromjson-0.1.9.tgz", + "integrity": "sha1-ZpELZkxp+jxQoc553R391bq0b24=", + "dependencies": { + "ngraph.graph": "0.0.14" + } + }, + "node_modules/ngraph.generators": { + "version": "0.0.19", + "resolved": "https://registry.npmjs.org/ngraph.generators/-/ngraph.generators-0.0.19.tgz", + "integrity": "sha1-VSwNCH+UK50NKwxsqarENr76dlk=", + "dependencies": { + "ngraph.graph": "0.0.14", + "ngraph.random": "0.1.0" + } + }, + "node_modules/ngraph.generators/node_modules/ngraph.random": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ngraph.random/-/ngraph.random-0.1.0.tgz", + "integrity": "sha1-G26Vc1KeCAZ32m/6CYeQ12oJSKk=" + }, + "node_modules/ngraph.graph": { + "version": "0.0.14", + "resolved": "https://registry.npmjs.org/ngraph.graph/-/ngraph.graph-0.0.14.tgz", + "integrity": "sha1-1HrJSWfJIKr3aVLYpOczRuHfLbc=", + "dependencies": { + "ngraph.events": "0.0.3" + } + }, + "node_modules/ngraph.merge": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/ngraph.merge/-/ngraph.merge-0.0.1.tgz", + "integrity": "sha1-5OgM43WBo8lrF9VF46Q8hUNLkCU=" + }, + "node_modules/ngraph.physics.primitives": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ngraph.physics.primitives/-/ngraph.physics.primitives-0.0.7.tgz", + "integrity": "sha1-Xcnhebofkubex3SwHNaJFBILeVs=" + }, + "node_modules/ngraph.physics.simulator": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/ngraph.physics.simulator/-/ngraph.physics.simulator-0.3.0.tgz", + "integrity": "sha1-fKb8PjYXxz4QgFcuqo4E27d+AQI=", + "dependencies": { + "ngraph.events": "0.0.3", + "ngraph.expose": "0.0.0", + "ngraph.merge": "0.0.1", + "ngraph.physics.primitives": "0.0.7", + "ngraph.quadtreebh": "0.0.4", + "ngraph.random": "0.0.1" + } + }, + "node_modules/ngraph.quadtreebh": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/ngraph.quadtreebh/-/ngraph.quadtreebh-0.0.4.tgz", + "integrity": "sha1-xwDUTm5K8HttBQAbo5h/9eLc1iw=", + "dependencies": { + "ngraph.random": "0.0.1" + } + }, + "node_modules/ngraph.random": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/ngraph.random/-/ngraph.random-0.0.1.tgz", + "integrity": "sha1-wAji67/f+vF+0Q5LvJE+VnFmvPg=" + }, + "node_modules/ngraph.remove-overlaps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ngraph.remove-overlaps/-/ngraph.remove-overlaps-1.0.0.tgz", + "integrity": "sha1-tMBjVT6kzx/3gWjnt//2JhfA2fQ=", + "dev": true + }, + "node_modules/ngraph.tojson": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/ngraph.tojson/-/ngraph.tojson-0.1.4.tgz", + "integrity": "sha1-OfAEZYhECt5iLVhzTVideXSgs7w=" + }, + "node_modules/nopt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-2.2.1.tgz", + "integrity": "sha1-KqCbfRdoSHs7ianFqlIzW/8Lrqc=", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "dev": true, + "dependencies": { + "once": "^1.3.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "dependencies": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "dependencies": { + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "dependencies": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true, + "dependencies": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.reduce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", + "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", + "dev": true, + "dependencies": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/optimist": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=", + "dev": true, + "dependencies": { + "wordwrap": "~0.0.2" + } + }, + "node_modules/ordered-read-streams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.1" + } + }, + "node_modules/ordered-read-streams/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/ordered-read-streams/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/ordered-read-streams/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/ordered-read-streams/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/os-browserify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.1.2.tgz", + "integrity": "sha1-ScoCk+CxlZCl9d4Qx/JlphfY/lQ=", + "dev": true + }, + "node_modules/os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "dependencies": { + "lcid": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", + "dev": true + }, + "node_modules/parents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", + "dev": true, + "dependencies": { + "path-platform": "~0.11.15" + } + }, + "node_modules/parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dev": true, + "dependencies": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "dev": true, + "dependencies": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "dependencies": { + "error-ex": "^1.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true + }, + "node_modules/path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "node_modules/path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "dependencies": { + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "node_modules/path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "node_modules/path-platform": { + "version": "0.11.15", + "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "dependencies": { + "path-root-regex": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pbkdf2": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", + "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "dev": true, + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/process": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/process/-/process-0.10.1.tgz", + "integrity": "sha1-hCRXzFHP7XLcd1r+6vuMYDQ3JyU=", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "dependencies": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "node_modules/punycode": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.2.4.tgz", + "integrity": "sha1-VACKyXKux0F13vnLpt9/qdORh0A=", + "dev": true, + "engines": [ + "node", + "rhino" + ] + }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "node_modules/read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "dependencies": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "dependencies": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/readable-wrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/readable-wrap/-/readable-wrap-1.0.0.tgz", + "integrity": "sha1-O1ohHGMeEjA6VJkcgGwX564ga/8=", + "dev": true, + "dependencies": { + "readable-stream": "^1.1.13-1" + } + }, + "node_modules/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/readdirp/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/readdirp/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readdirp/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/readdirp/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/rechoir/node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "dependencies": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regex-not/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regex-not/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/remove-bom-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/remove-bom-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", + "dev": true, + "dependencies": { + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/remove-bom-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/remove-bom-stream/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/remove-bom-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/remove-bom-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/remove-bom-stream/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/remove-bom-stream/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "node_modules/repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/replace-homedir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", + "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1", + "is-absolute": "^1.0.0", + "remove-trailing-separator": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "node_modules/resolve": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.7.4.tgz", + "integrity": "sha1-OVqe+ehz+/4SvRRAi9kbuTYAPWk=", + "dev": true + }, + "node_modules/resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", + "dev": true, + "dependencies": { + "value-or-function": "^3.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "deprecated": "https://github.com/lydell/resolve-url#deprecated", + "dev": true + }, + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/rfile": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rfile/-/rfile-1.0.0.tgz", + "integrity": "sha1-WXCM+Qyh50xUw8/Fw2/bmBBDUmE=", + "dev": true, + "dependencies": { + "callsite": "~1.0.0", + "resolve": "~0.3.0" + } + }, + "node_modules/rfile/node_modules/resolve": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.3.1.tgz", + "integrity": "sha1-NMY0R8ZkxwWY0cmxJvxDsqJDEKQ=", + "dev": true + }, + "node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/ruglify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ruglify/-/ruglify-1.0.0.tgz", + "integrity": "sha1-3Ikw4qlUSidDAcyZcldMDQmGtnU=", + "dev": true, + "dependencies": { + "rfile": "~1.0", + "uglify-js": "~2.2" + } + }, + "node_modules/ruglify/node_modules/uglify-js": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.2.5.tgz", + "integrity": "sha1-puAqcNg5eSuXgEiLe4sYTAlcmcc=", + "dev": true, + "dependencies": { + "optimist": "~0.3.5", + "source-map": "~0.1.7" + }, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/runforcover": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/runforcover/-/runforcover-0.0.2.tgz", + "integrity": "sha1-NE8FfY1F0zrrxsyCIEZ49pxIV8w=", + "dev": true, + "dependencies": { + "bunker": "0.1.X" + }, + "engines": { + "node": "*" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "dependencies": { + "ret": "~0.1.10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/semver-greatest-satisfied-range": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", + "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", + "dev": true, + "dependencies": { + "sver-compat": "^1.5.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "node_modules/set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/shallow-copy": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", + "integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=", + "dev": true + }, + "node_modules/shasum": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", + "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", + "dev": true, + "dependencies": { + "json-stable-stringify": "~0.0.0", + "sha.js": "~2.4.4" + } + }, + "node_modules/shell-quote": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-0.0.1.tgz", + "integrity": "sha1-GkEZbzwDM8SCMjWT1ohuzxU92YY=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "node_modules/simplesvg": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/simplesvg/-/simplesvg-0.0.10.tgz", + "integrity": "sha1-N9LsGN4sFU3Ztp956K0gvx4eX90=", + "dependencies": { + "add-event-listener": "0.0.1" + } + }, + "node_modules/slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "dependencies": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "dependencies": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "dependencies": { + "kind-of": "^3.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "dependencies": { + "amdefine": ">=0.0.4" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "dependencies": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "node_modules/source-map-url": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", + "dev": true + }, + "node_modules/sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz", + "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==", + "dev": true + }, + "node_modules/split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "dependencies": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stream-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-1.0.0.tgz", + "integrity": "sha1-v5tKv7QrJ011FHnkTg/yZWtvEZM=", + "dev": true, + "dependencies": { + "inherits": "~2.0.1", + "readable-stream": "^1.0.27-1" + } + }, + "node_modules/stream-combiner2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.0.2.tgz", + "integrity": "sha1-unKmtQy/q/qVD8i8h2BL0B62BnE=", + "dev": true, + "dependencies": { + "duplexer2": "~0.0.2", + "through2": "~0.5.1" + } + }, + "node_modules/stream-combiner2/node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/stream-combiner2/node_modules/through2": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", + "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", + "dev": true, + "dependencies": { + "readable-stream": "~1.0.17", + "xtend": "~3.0.0" + } + }, + "node_modules/stream-exhaust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", + "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", + "dev": true + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "node_modules/stream-splicer": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-1.3.2.tgz", + "integrity": "sha1-PARBvhW5v04iYnXm3IOWR0VUZmE=", + "dev": true, + "dependencies": { + "indexof": "0.0.1", + "inherits": "^2.0.1", + "isarray": "~0.0.1", + "readable-stream": "^1.1.13-1", + "readable-wrap": "^1.0.0", + "through2": "^1.0.0" + } + }, + "node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "dependencies": { + "is-utf8": "^0.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/subarg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", + "dev": true, + "dependencies": { + "minimist": "^1.1.0" + } + }, + "node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/sver-compat": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", + "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", + "dev": true, + "dependencies": { + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/syntax-error": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", + "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", + "dev": true, + "dependencies": { + "acorn-node": "^1.2.0" + } + }, + "node_modules/tap": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/tap/-/tap-0.4.13.tgz", + "integrity": "sha1-OYYTTWdZcn/CIj5hEm7rhyQ6zLw=", + "dev": true, + "dependencies": { + "buffer-equal": "~0.0.0", + "deep-equal": "~0.0.0", + "difflet": "~0.2.0", + "glob": "~3.2.1", + "inherits": "*", + "mkdirp": "~0.3 || 0.4 || 0.5", + "nopt": "~2", + "runforcover": "~0.0.2", + "slide": "*", + "yamlish": "*" + }, + "bin": { + "tap": "bin/tap.js" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tap/node_modules/deep-equal": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.0.0.tgz", + "integrity": "sha1-mWedO70EcVb81FDT0B7rkGhpHoM=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/tap/node_modules/glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "dev": true, + "dependencies": { + "inherits": "2", + "minimatch": "0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tap/node_modules/minimatch": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "deprecated": "Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue", + "dev": true, + "dependencies": { + "lru-cache": "2", + "sigmund": "~1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "node_modules/through2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-1.1.1.tgz", + "integrity": "sha1-CEfLxESfNAVXTb3M2buEG4OsNUU=", + "dev": true, + "dependencies": { + "readable-stream": ">=1.1.13-1 <1.2.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + }, + "node_modules/through2-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", + "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", + "dev": true, + "dependencies": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + } + }, + "node_modules/through2-filter/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/through2-filter/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/through2-filter/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/through2-filter/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/through2-filter/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/through2-filter/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/through2/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/timers-browserify": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", + "dev": true, + "dependencies": { + "process": "~0.11.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/timers-browserify/node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/to-absolute-glob": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", + "dev": true, + "dependencies": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "dependencies": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", + "dev": true, + "dependencies": { + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/to-through/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/to-through/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/to-through/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/to-through/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/to-through/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/to-through/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/traverse": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", + "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=", + "dev": true + }, + "node_modules/tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", + "dev": true + }, + "node_modules/type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "node_modules/uglify-js": { + "version": "3.12.8", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.12.8.tgz", + "integrity": "sha512-fvBeuXOsvqjecUtF/l1dwsrrf5y2BCUk9AOJGzGcm6tE7vegku5u/YvqjyDaAGr422PLoLnrxg3EnRvTqsdC1w==", + "dev": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true + }, + "node_modules/umd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/umd/-/umd-2.1.0.tgz", + "integrity": "sha1-SmMHt2LxfwLSAbX6FU5nM5bCY88=", + "dev": true, + "dependencies": { + "rfile": "~1.0.0", + "ruglify": "~1.0.0", + "through": "~2.3.4", + "uglify-js": "~2.4.0" + }, + "bin": { + "umd": "bin/cli.js" + } + }, + "node_modules/umd/node_modules/async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "node_modules/umd/node_modules/camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/umd/node_modules/source-map": { + "version": "0.1.34", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.34.tgz", + "integrity": "sha1-p8/omux7FoLDsZjQrPtH19CQVms=", + "dev": true, + "dependencies": { + "amdefine": ">=0.0.4" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/umd/node_modules/uglify-js": { + "version": "2.4.24", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.24.tgz", + "integrity": "sha1-+tV1XB4Vd2WLsG/5q25UjJW+vW4=", + "dev": true, + "dependencies": { + "async": "~0.2.6", + "source-map": "0.1.34", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.5.4" + }, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/umd/node_modules/wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/umd/node_modules/yargs": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.5.4.tgz", + "integrity": "sha1-2K/49mXpTDS9JZvevRv68N3TU2E=", + "dev": true, + "dependencies": { + "camelcase": "^1.0.2", + "decamelize": "^1.0.0", + "window-size": "0.1.0", + "wordwrap": "0.0.2" + } + }, + "node_modules/unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/undertaker": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", + "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "fast-levenshtein": "^1.0.0", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "dependencies": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unique-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", + "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", + "dev": true, + "dependencies": { + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "^3.0.0" + } + }, + "node_modules/unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "dependencies": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "dependencies": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true, + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "deprecated": "Please see https://github.com/lydell/urix#deprecated", + "dev": true + }, + "node_modules/url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "dev": true, + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + }, + "node_modules/use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "dev": true, + "dependencies": { + "inherits": "2.0.3" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "node_modules/util/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "node_modules/v8flags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "dependencies": { + "clone": "^0.2.0", + "clone-stats": "^0.0.1" + }, + "engines": { + "node": ">= 0.9" + } + }, + "node_modules/vinyl-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vinyl-buffer/-/vinyl-buffer-1.0.1.tgz", + "integrity": "sha1-lsGjR5uMU5JULGEgKQE7Wyf4i78=", + "dev": true, + "dependencies": { + "bl": "^1.2.1", + "through2": "^2.0.3" + } + }, + "node_modules/vinyl-buffer/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/vinyl-buffer/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/vinyl-buffer/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/vinyl-buffer/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/vinyl-buffer/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/vinyl-buffer/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "dependencies": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-fs/node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/vinyl-fs/node_modules/clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "node_modules/vinyl-fs/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/vinyl-fs/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/vinyl-fs/node_modules/replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-fs/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/vinyl-fs/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/vinyl-fs/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/vinyl-fs/node_modules/vinyl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", + "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", + "dev": true, + "dependencies": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-fs/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/vinyl-source-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-2.0.0.tgz", + "integrity": "sha1-84pa+53R6Ttl1VBGmsYYKsT1S44=", + "dev": true, + "dependencies": { + "through2": "^2.0.3", + "vinyl": "^2.1.0" + } + }, + "node_modules/vinyl-source-stream/node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/vinyl-source-stream/node_modules/clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "node_modules/vinyl-source-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/vinyl-source-stream/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/vinyl-source-stream/node_modules/replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-source-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/vinyl-source-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/vinyl-source-stream/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/vinyl-source-stream/node_modules/vinyl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", + "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", + "dev": true, + "dependencies": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-source-stream/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", + "dev": true, + "dependencies": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-sourcemap/node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/vinyl-sourcemap/node_modules/clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "node_modules/vinyl-sourcemap/node_modules/convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/vinyl-sourcemap/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vinyl-sourcemap/node_modules/replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-sourcemap/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/vinyl-sourcemap/node_modules/vinyl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", + "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", + "dev": true, + "dependencies": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-sourcemaps-apply": { "version": "0.2.1", - "resolved": "https://registry.npmjs.org/Base64/-/Base64-0.2.1.tgz", - "integrity": "sha1-ujpCMHCOGGcFBl5mur3Uw1z2ACg=", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", + "dev": true, + "dependencies": { + "source-map": "^0.5.1" + } + }, + "node_modules/vinyl-sourcemaps-apply/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "dependencies": { + "indexof": "0.0.1" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", "dev": true }, - "JSONStream": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.8.4.tgz", - "integrity": "sha1-kWV9/m/4V0gwZhMrRhi2Lo9Ih70=", + "node_modules/window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", "dev": true, - "requires": { - "jsonparse": "0.0.5", - "through": ">=2.2.7 <3" + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/xtend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", + "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", + "dev": true, + "engines": { + "node": ">=0.4" } }, + "node_modules/y18n": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", + "dev": true + }, + "node_modules/yamlish": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/yamlish/-/yamlish-0.0.7.tgz", + "integrity": "sha1-tK+aHcxjYYhzw9bkUewyE8OaV/s=", + "dev": true + }, + "node_modules/yargs": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.1.tgz", + "integrity": "sha512-huO4Fr1f9PmiJJdll5kwoS2e4GqzGSsMT3PPMpOwoVkOK8ckqAewMTZyA6LXVQWflleb/Z8oPBEvNsMft0XE+g==", + "dev": true, + "dependencies": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "5.0.0-security.0" + } + }, + "node_modules/yargs-parser": { + "version": "5.0.0-security.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0-security.0.tgz", + "integrity": "sha512-T69y4Ps64LNesYxeYGYPvfoMTt/7y1XtfpIslUeK4um+9Hu7hlGoRtaDLvdXb7+/tfq4opVa2HRY5xGip022rQ==", + "dev": true, + "dependencies": { + "camelcase": "^3.0.0", + "object.assign": "^4.1.0" + } + } + }, + "dependencies": { "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -44,9 +7542,9 @@ }, "dependencies": { "acorn": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", - "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "dev": true }, "xtend": { @@ -58,9 +7556,9 @@ } }, "acorn-walk": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.0.0.tgz", - "integrity": "sha512-7Bv1We7ZGuU79zZbb6rRqcpxo3OY+zrdtloZWoyD8fmGX+FeXRjE+iuGkZjSXLVovLzrsvMGMy0EkwA0E0umxg==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", "dev": true }, "add-event-listener": { @@ -68,34 +7566,21 @@ "resolved": "https://registry.npmjs.org/add-event-listener/-/add-event-listener-0.0.1.tgz", "integrity": "sha1-p2Ip68ZMiu+uIEoWJzovJVq+otA=" }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, - "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", "dev": true }, + "ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "requires": { + "ansi-wrap": "^0.1.0" + } + }, "ansi-gray": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", @@ -123,6 +7608,44 @@ "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", "dev": true }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "append-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", + "dev": true, + "requires": { + "buffer-equal": "^1.0.0" + }, + "dependencies": { + "buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", + "dev": true + } + } + }, "archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", @@ -135,12 +7658,30 @@ "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", "dev": true }, + "arr-filter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", + "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } + }, "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", "dev": true }, + "arr-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", + "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } + }, "arr-union": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", @@ -159,12 +7700,58 @@ "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", "dev": true }, + "array-initial": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", + "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", + "dev": true, + "requires": { + "array-slice": "^1.0.0", + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "array-last": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", + "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", + "dev": true, + "requires": { + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, "array-slice": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", "dev": true }, + "array-sort": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", + "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", + "dev": true, + "requires": { + "default-compare": "^1.0.0", + "get-value": "^2.0.6", + "kind-of": "^5.0.2" + } + }, "array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", @@ -187,14 +7774,23 @@ "dev": true }, "asn1.js": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", "dev": true, "requires": { "bn.js": "^4.0.0", "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } } }, "assert": { @@ -239,17 +7835,61 @@ } }, "async": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "async-done": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", + "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.2", + "process-nextick-args": "^2.0.0", + "stream-exhaust": "^1.0.1" + } + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", "dev": true }, + "async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", + "dev": true, + "requires": { + "async-done": "^1.2.2" + } + }, "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, + "bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", + "dev": true, + "requires": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + } + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -279,38 +7919,15 @@ "requires": { "is-descriptor": "^1.0.0" } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } } } }, + "Base64": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/Base64/-/Base64-0.2.1.tgz", + "integrity": "sha1-ujpCMHCOGGcFBl5mur3Uw1z2ACg=", + "dev": true + }, "base64-js": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", @@ -323,10 +7940,26 @@ "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", "dev": true }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, "bl": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", - "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", "dev": true, "requires": { "readable-stream": "^2.3.5", @@ -340,9 +7973,9 @@ "dev": true }, "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -352,16 +7985,14 @@ "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } } }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -369,22 +8000,14 @@ "dev": true, "requires": { "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } } } } }, "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", "dev": true }, "brace-expansion": { @@ -413,17 +8036,6 @@ "snapdragon-node": "^2.0.1", "split-string": "^3.0.2", "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } } }, "brorand": { @@ -438,10 +8050,10 @@ "integrity": "sha1-+qHLxBSHsazEdH43PhFIrf/Q4tk=", "dev": true, "requires": { - "JSONStream": "~0.8.4", "combine-source-map": "~0.3.0", "concat-stream": "~1.4.1", "defined": "~0.0.0", + "JSONStream": "~0.8.4", "through2": "~0.5.1", "umd": "^2.1.0" }, @@ -493,7 +8105,6 @@ "integrity": "sha1-8zpUmjpsNoIZsHX9z+bfGV4Empo=", "dev": true, "requires": { - "JSONStream": "~0.8.3", "assert": "~1.3.0", "browser-pack": "^3.2.0", "browser-resolve": "^1.3.0", @@ -517,6 +8128,7 @@ "inherits": "~2.0.1", "insert-module-globals": "^6.2.0", "isarray": "0.0.1", + "JSONStream": "~0.8.3", "labeled-stream-splicer": "^1.0.0", "module-deps": "^3.6.3", "os-browserify": "~0.1.1", @@ -582,28 +8194,52 @@ } }, "browserify-rsa": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", "dev": true, "requires": { - "bn.js": "^4.1.0", + "bn.js": "^5.0.0", "randombytes": "^2.0.1" } }, "browserify-sign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", - "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "dev": true, - "requires": { - "bn.js": "^4.1.1", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.2", - "elliptic": "^6.0.0", - "inherits": "^2.0.1", - "parse-asn1": "^5.0.0" + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dev": true, + "requires": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + } } }, "browserify-zlib": { @@ -616,9 +8252,9 @@ } }, "buffer": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz", - "integrity": "sha1-pyyTb3e5a/UvX357RnGAYoVR3vs=", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-3.6.2.tgz", + "integrity": "sha512-c3M77NkHJxS0zx/ErxXhDLr1v3y2MDXPeTJPvLNOaIYJ4ymHBUFQ9EXzt9HYuqAJllMoNb/EZ8hIiulnQFAUuQ==", "dev": true, "requires": { "base64-js": "0.0.8", @@ -640,6 +8276,12 @@ "integrity": "sha1-7Lt5D1aNQAmKYkK1SAXHWAXrk48=", "dev": true }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, "buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", @@ -702,6 +8344,16 @@ "unset-value": "^1.0.0" } }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, "callsite": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", @@ -709,21 +8361,11 @@ "dev": true }, "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", "dev": true }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, - "requires": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" - } - }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", @@ -743,6 +8385,26 @@ "integrity": "sha1-BsIe7RobBq62dVPNxT4jJ0usIpY=", "dev": true }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -773,32 +8435,81 @@ "requires": { "is-descriptor": "^0.1.0" } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } } } }, "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "dev": true, "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" - }, - "dependencies": { - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true - } + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" } }, "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", "dev": true }, "clone-stats": { @@ -807,6 +8518,72 @@ "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", "dev": true }, + "cloneable-readable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", + "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "collection-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", + "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", + "dev": true, + "requires": { + "arr-map": "^2.0.2", + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -864,13 +8641,10 @@ } }, "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true, - "requires": { - "date-now": "^0.1.4" - } + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true }, "constants-browserify": { "version": "0.0.1", @@ -890,6 +8664,16 @@ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, + "copy-props": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", + "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", + "dev": true, + "requires": { + "each-props": "^1.3.0", + "is-plain-object": "^2.0.1" + } + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -897,13 +8681,21 @@ "dev": true }, "create-ecdh": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", - "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", "dev": true, "requires": { "bn.js": "^4.1.0", - "elliptic": "^6.0.0" + "elliptic": "^6.5.3" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } } }, "create-hash": { @@ -952,11 +8744,15 @@ "randomfill": "^1.0.3" } }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", - "dev": true + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } }, "dateformat": { "version": "2.2.0", @@ -964,12 +8760,6 @@ "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", "dev": true }, - "deap": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/deap/-/deap-1.0.1.tgz", - "integrity": "sha512-k75KYNZMvwAwes2xIPry/QTffXIchjD8QfABvvfTr80P85jv5ZcKqcoDo+vMe71nNnVnXYe8MA28weyqcf/DKw==", - "dev": true - }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -1003,13 +8793,28 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "default-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", + "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", "dev": true, "requires": { - "clone": "^1.0.2" + "kind-of": "^5.0.2" + } + }, + "default-resolution": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", + "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" } }, "define-property": { @@ -1020,37 +8825,6 @@ "requires": { "is-descriptor": "^1.0.2", "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } } }, "defined": { @@ -1073,12 +8847,6 @@ "rimraf": "^2.2.8" } }, - "deprecated": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", - "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", - "dev": true - }, "deps-sort": { "version": "1.3.9", "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-1.3.9.tgz", @@ -1091,6 +8859,12 @@ "through2": "^1.0.0" }, "dependencies": { + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, "JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", @@ -1100,19 +8874,13 @@ "jsonparse": "^1.2.0", "through": ">=2.2.7 <3" } - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", - "dev": true } } }, "des.js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", - "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", "dev": true, "requires": { "inherits": "^2.0.1", @@ -1136,9 +8904,9 @@ }, "dependencies": { "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "version": "5.7.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", + "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", "dev": true }, "defined": { @@ -1158,6 +8926,14 @@ "bn.js": "^4.1.0", "miller-rabin": "^4.0.0", "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } } }, "difflet": { @@ -1177,58 +8953,168 @@ "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", "dev": true }, - "duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "requires": { + "readable-stream": "~1.1.9" + } + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "each-async": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/each-async/-/each-async-1.1.1.tgz", + "integrity": "sha1-3uUim98KtrogEqOV4bhpq/iBNHM=", + "dev": true, + "requires": { + "onetime": "^1.0.0", + "set-immediate-shim": "^1.0.0" + } + }, + "each-props": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", + "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.1", + "object.defaults": "^1.1.0" + } + }, + "elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dev": true, + "requires": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "requires": { - "readable-stream": "~1.1.9" + "is-arrayish": "^0.2.1" } }, - "each-async": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/each-async/-/each-async-1.1.1.tgz", - "integrity": "sha1-3uUim98KtrogEqOV4bhpq/iBNHM=", + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", "dev": true, "requires": { - "onetime": "^1.0.0", - "set-immediate-shim": "^1.0.0" + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" } }, - "elliptic": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.1.tgz", - "integrity": "sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg==", + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", "dev": true, "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" } }, - "end-of-stream": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", - "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", "dev": true, "requires": { - "once": "~1.3.0" - }, - "dependencies": { - "once": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "dev": true, - "requires": { - "wrappy": "1" - } - } + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" } }, "escape-string-regexp": { @@ -1277,13 +9163,55 @@ "is-descriptor": "^0.1.0" } }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" } } } @@ -1297,6 +9225,23 @@ "homedir-polyfill": "^1.0.1" } }, + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.3.0.tgz", + "integrity": "sha512-rgPIqOdfK/4J9FhiVrZ3cveAjRRo5rsQBAIhnylX874y1DX/kEKSVdLsnuHB6l1KTjHyU01VjiMBHgU2adejyg==", + "dev": true + } + } + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -1304,24 +9249,12 @@ "dev": true }, "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } + "is-extendable": "^0.1.0" } }, "extglob": { @@ -1348,44 +9281,6 @@ "requires": { "is-descriptor": "^1.0.0" } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } } } }, @@ -1401,6 +9296,19 @@ "time-stamp": "^1.0.0" } }, + "fast-levenshtein": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", + "integrity": "sha1-5qdUzI8V5YmHqpy9J69m/W9OWvk=", + "dev": true + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -1411,99 +9319,223 @@ "is-number": "^3.0.0", "repeat-string": "^1.6.1", "to-regex-range": "^2.1.0" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + } + }, + "flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "dev": true + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" }, "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true } } }, - "find-index": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", - "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", - "dev": true - }, - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - } - }, - "first-chunk-stream": { + "fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", - "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", - "dev": true - }, - "flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", - "dev": true - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", "dev": true, + "optional": true, "requires": { - "for-in": "^1.0.1" + "bindings": "^1.5.0", + "nan": "^2.12.1" } }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", "dev": true }, - "gaze": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", - "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", "dev": true, "requires": { - "globule": "~0.1.0" + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" } }, "get-value": { @@ -1529,66 +9561,119 @@ "once": "^1.3.0" } }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, "glob-stream": { - "version": "3.1.18", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", - "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", "dev": true, "requires": { - "glob": "^4.3.1", - "glob2base": "^0.0.12", - "minimatch": "^2.0.1", - "ordered-read-streams": "^0.1.0", - "through2": "^0.6.1", - "unique-stream": "^1.0.0" + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" }, "dependencies": { - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" + "brace-expansion": "^1.1.7" } }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } } } }, "glob-watcher": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", - "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", - "dev": true, - "requires": { - "gaze": "^0.5.1" - } - }, - "glob2base": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", - "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", + "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", "dev": true, "requires": { - "find-index": "^0.1.1" + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "normalize-path": "^3.0.0", + "object.defaults": "^1.1.0" } }, "global-modules": { @@ -1627,12 +9712,6 @@ "object-assign": "^3.0.0" }, "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, "glob": { "version": "5.0.15", "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", @@ -1648,52 +9727,6 @@ } } }, - "globule": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", - "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", - "dev": true, - "requires": { - "glob": "~3.1.21", - "lodash": "~1.0.1", - "minimatch": "~0.2.11" - }, - "dependencies": { - "glob": { - "version": "3.1.21", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", - "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", - "dev": true, - "requires": { - "graceful-fs": "~1.2.0", - "inherits": "1", - "minimatch": "~0.2.11" - } - }, - "graceful-fs": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", - "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", - "dev": true - }, - "inherits": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", - "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", - "dev": true - }, - "minimatch": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", - "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "dev": true, - "requires": { - "lru-cache": "2", - "sigmund": "~1.0.0" - } - } - } - }, "glogg": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", @@ -1704,39 +9737,103 @@ } }, "graceful-fs": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.12.tgz", - "integrity": "sha512-J55gaCS4iTTJfTXIxSVw3EMQckcqkpdRv3IR7gu6sq0+tbC363Zx6KH/SEwXASK9JRbhyZmVjJEVJIOxYsB3Qg==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "dev": true + }, + "gulp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", "dev": true, "requires": { - "natives": "^1.1.3" + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" } }, - "gulp": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", - "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", + "gulp-cli": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", + "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", "dev": true, "requires": { + "ansi-colors": "^1.0.1", "archy": "^1.0.0", - "chalk": "^1.0.0", - "deprecated": "^0.0.1", - "gulp-util": "^3.0.0", - "interpret": "^1.0.0", - "liftoff": "^2.1.0", - "minimist": "^1.1.0", - "orchestrator": "^0.3.0", + "array-sort": "^1.0.0", + "color-support": "^1.1.3", + "concat-stream": "^1.6.0", + "copy-props": "^2.0.1", + "fancy-log": "^1.3.2", + "gulplog": "^1.0.0", + "interpret": "^1.4.0", + "isobject": "^3.0.1", + "liftoff": "^3.1.0", + "matchdep": "^2.0.0", + "mute-stdout": "^1.0.0", "pretty-hrtime": "^1.0.0", - "semver": "^4.1.0", - "tildify": "^1.0.0", - "v8flags": "^2.0.2", - "vinyl-fs": "^0.3.0" + "replace-homedir": "^1.0.0", + "semver-greatest-satisfied-range": "^1.1.0", + "v8flags": "^3.2.0", + "yargs": "^7.1.0" + }, + "dependencies": { + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "gulp-rename": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.4.0.tgz", - "integrity": "sha512-swzbIGb/arEoFK89tPY58vg3Ok1bw+d35PfUNwWqdo7KM4jkmuGA78JiDNqR+JeZFaeeHnRg9N7aihX3YPmsyg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-2.0.0.tgz", + "integrity": "sha512-97Vba4KBzbYmR5VBs9mWmK+HwIf5mj+/zioxfZhOKeXtx5ZjBk57KFlePf5nxq9QsTtFl0ejnHE3zTC9MHXqyQ==", "dev": true }, "gulp-run": { @@ -1749,80 +9846,55 @@ "lodash.defaults": "^4.0.1", "lodash.template": "^4.0.2", "vinyl": "^0.4.6" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "lodash.template": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", - "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", - "dev": true, - "requires": { - "lodash._reinterpolate": "^3.0.0", - "lodash.templatesettings": "^4.0.0" - } - }, - "lodash.templatesettings": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", - "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", - "dev": true, - "requires": { - "lodash._reinterpolate": "^3.0.0" - } - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "^0.2.0", - "clone-stats": "^0.0.1" - } - } } }, "gulp-uglify": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-1.5.4.tgz", - "integrity": "sha1-UkeI2HZm0J+dDCH7IXf5ADmmWMk=", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.2.tgz", + "integrity": "sha512-gk1dhB74AkV2kzqPMQBLA3jPoIAPd/nlNzP2XMDSG8XZrqnlCiDGAqC+rZOumzFvB5zOphlFh6yr3lgcAb/OOg==", "dev": true, "requires": { - "deap": "^1.0.0", - "fancy-log": "^1.0.0", - "gulp-util": "^3.0.0", - "isobject": "^2.0.0", + "array-each": "^1.0.1", + "extend-shallow": "^3.0.2", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "isobject": "^3.0.1", + "make-error-cause": "^1.1.1", + "safe-buffer": "^5.1.2", "through2": "^2.0.0", - "uglify-js": "2.6.4", - "uglify-save-license": "^0.4.1", + "uglify-js": "^3.0.5", "vinyl-sourcemaps-apply": "^0.2.0" }, "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - }, "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -1840,12 +9912,6 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -1865,35 +9931,11 @@ "xtend": "~4.0.1" } }, - "uglify-js": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.6.4.tgz", - "integrity": "sha1-ZeovswWck5RpLxX+2HwrNsFrmt8=", - "dev": true, - "requires": { - "async": "~0.2.6", - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" - } - }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" - } } } }, @@ -1923,16 +9965,49 @@ "vinyl": "^0.5.0" }, "dependencies": { + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "dev": true, + "requires": { + "lodash._basecopy": "^3.0.0", + "lodash._basetostring": "^3.0.0", + "lodash._basevalues": "^3.0.0", + "lodash._isiterateecall": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0", + "lodash.keys": "^3.0.0", + "lodash.restparam": "^3.0.0", + "lodash.templatesettings": "^3.0.0" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0" + } + }, "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -1969,6 +10044,17 @@ "xtend": "~4.0.1" } }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -1986,6 +10072,15 @@ "glogg": "^1.0.0" } }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, "has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", @@ -2004,6 +10099,12 @@ "sparkles": "^1.0.0" } }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -2037,13 +10138,36 @@ } }, "hash-base": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", "dev": true, "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + } } }, "hash.js": { @@ -2076,6 +10200,12 @@ "parse-passwd": "^1.0.0" } }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, "http-browserify": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/http-browserify/-/http-browserify-1.7.0.tgz", @@ -2093,9 +10223,9 @@ "dev": true }, "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "dev": true }, "indexof": { @@ -2121,9 +10251,9 @@ "dev": true }, "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, "inline-source-map": { @@ -2152,26 +10282,16 @@ "integrity": "sha1-IGOOKaMPntHKLjqCX7wsulJG3fw=", "dev": true, "requires": { - "JSONStream": "^1.0.3", "combine-source-map": "~0.6.1", "concat-stream": "~1.4.1", "is-buffer": "^1.1.0", + "JSONStream": "^1.0.3", "lexical-scope": "^1.2.0", "process": "~0.11.0", "through2": "^1.0.0", "xtend": "^4.0.0" }, "dependencies": { - "JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dev": true, - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, "combine-source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.6.1.tgz", @@ -2205,6 +10325,16 @@ "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true }, + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -2229,9 +10359,15 @@ } }, "interpret": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", - "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, "is-absolute": { @@ -2245,66 +10381,84 @@ } }, "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "^6.0.0" }, "dependencies": { "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true } } }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, + "is-core-module": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", + "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "^6.0.0" }, "dependencies": { "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true } } }, "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" }, "dependencies": { "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true } } @@ -2321,15 +10475,30 @@ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", "dev": true, "requires": { - "is-extglob": "^2.1.0" + "is-extglob": "^2.1.1" } }, + "is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", + "dev": true + }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -2407,6 +10576,12 @@ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", "dev": true }, + "is-valid-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", + "dev": true + }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -2431,50 +10606,141 @@ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, - "json-stable-stringify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", - "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", + "json-stable-stringify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", + "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", + "dev": true, + "requires": { + "jsonify": "~0.0.0" + } + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonparse": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz", + "integrity": "sha1-MwVCrT8KZUZlt3jz6y2an6UHrGQ=", + "dev": true + }, + "JSONStream": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.8.4.tgz", + "integrity": "sha1-kWV9/m/4V0gwZhMrRhi2Lo9Ih70=", + "dev": true, + "requires": { + "jsonparse": "0.0.5", + "through": ">=2.2.7 <3" + } + }, + "just-debounce": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.1.0.tgz", + "integrity": "sha512-qpcRocdkUmf+UTNBYx5w6dexX5J31AKK1OmPwH630a83DdVVUIngk55RSAiIGpQyoH0dlr872VHfPjnQnK1qDQ==", + "dev": true + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + }, + "labeled-stream-splicer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-1.0.2.tgz", + "integrity": "sha1-RhUzFTd4SYHo/SZOHzpDTE4N3WU=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "isarray": "~0.0.1", + "stream-splicer": "^1.1.0" + } + }, + "last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", + "dev": true, + "requires": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + } + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "requires": { + "readable-stream": "^2.0.5" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", "dev": true, "requires": { - "jsonify": "~0.0.0" + "invert-kv": "^1.0.0" } }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, - "jsonparse": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz", - "integrity": "sha1-MwVCrT8KZUZlt3jz6y2an6UHrGQ=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "labeled-stream-splicer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-1.0.2.tgz", - "integrity": "sha1-RhUzFTd4SYHo/SZOHzpDTE4N3WU=", + "lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", "dev": true, "requires": { - "inherits": "^2.0.1", - "isarray": "~0.0.1", - "stream-splicer": "^1.1.0" + "flush-write-stream": "^1.0.2" } }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true - }, "lexical-scope": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/lexical-scope/-/lexical-scope-1.2.0.tgz", @@ -2485,13 +10751,13 @@ } }, "liftoff": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", - "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", + "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", "dev": true, "requires": { "extend": "^3.0.0", - "findup-sync": "^2.0.0", + "findup-sync": "^3.0.0", "fined": "^1.0.1", "flagged-respawn": "^1.0.0", "is-plain-object": "^2.0.4", @@ -2501,21 +10767,29 @@ }, "dependencies": { "resolve": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", - "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", "dev": true, "requires": { + "is-core-module": "^2.2.0", "path-parse": "^1.0.6" } } } }, - "lodash": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", - "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", - "dev": true + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } }, "lodash._basecopy": { "version": "3.0.1", @@ -2622,44 +10896,45 @@ "dev": true }, "lodash.template": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", "dev": true, "requires": { - "lodash._basecopy": "^3.0.0", - "lodash._basetostring": "^3.0.0", - "lodash._basevalues": "^3.0.0", - "lodash._isiterateecall": "^3.0.0", "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0", - "lodash.keys": "^3.0.0", - "lodash.restparam": "^3.0.0", - "lodash.templatesettings": "^3.0.0" + "lodash.templatesettings": "^4.0.0" } }, "lodash.templatesettings": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", - "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", "dev": true, "requires": { - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0" + "lodash._reinterpolate": "^3.0.0" } }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true - }, "lru-cache": { "version": "2.7.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", "dev": true }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "make-error-cause": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", + "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=", + "dev": true, + "requires": { + "make-error": "^1.2.0" + } + }, "make-iterator": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", @@ -2667,6 +10942,14 @@ "dev": true, "requires": { "kind-of": "^6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + } } }, "map-cache": { @@ -2684,6 +10967,51 @@ "object-visit": "^1.0.0" } }, + "matchdep": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", + "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", + "dev": true, + "requires": { + "findup-sync": "^2.0.0", + "micromatch": "^3.0.4", + "resolve": "^1.4.0", + "stack-trace": "0.0.10" + }, + "dependencies": { + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + } + } + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -2714,6 +11042,33 @@ "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + } } }, "miller-rabin": { @@ -2724,6 +11079,14 @@ "requires": { "bn.js": "^4.0.0", "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } } }, "minimalistic-assert": { @@ -2748,9 +11111,9 @@ } }, "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, "mixin-deep": { @@ -2775,20 +11138,12 @@ } }, "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - } + "minimist": "^1.2.5" } }, "module-deps": { @@ -2797,13 +11152,13 @@ "integrity": "sha1-6nXK+RmQkNJbDVUStaysuW5/h/M=", "dev": true, "requires": { - "JSONStream": "^1.0.3", "browser-resolve": "^1.7.0", "concat-stream": "~1.4.5", "defined": "^1.0.0", "detective": "^4.0.0", "duplexer2": "0.0.2", "inherits": "^2.0.1", + "JSONStream": "^1.0.3", "parents": "^1.0.0", "readable-stream": "^1.1.13", "resolve": "^1.1.3", @@ -2813,16 +11168,6 @@ "xtend": "^4.0.0" }, "dependencies": { - "JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dev": true, - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, "defined": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", @@ -2835,12 +11180,23 @@ "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true }, + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, "resolve": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", - "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", "dev": true, "requires": { + "is-core-module": "^2.2.0", "path-parse": "^1.0.6" } }, @@ -2867,6 +11223,19 @@ "duplexer2": "0.0.2" } }, + "mute-stdout": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", + "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", + "dev": true + }, + "nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", + "dev": true, + "optional": true + }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -2884,12 +11253,39 @@ "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + } } }, - "natives": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.6.tgz", - "integrity": "sha512-6+TDFewD4yxY14ptjKaS63GVdtKiES1pTPyxn9Jb0rBqPMZ7VcCiooEhPNsr+mqHtMGxa/5c/HhcC4uPEUw/nA==", + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, "ngraph.centrality": { @@ -3011,6 +11407,51 @@ "abbrev": "1" } }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + } + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "dev": true, + "requires": { + "once": "^1.3.2" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, "object-assign": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", @@ -3037,6 +11478,43 @@ "is-descriptor": "^0.1.0" } }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -3048,6 +11526,12 @@ } } }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, "object-visit": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", @@ -3057,6 +11541,18 @@ "isobject": "^3.0.0" } }, + "object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, "object.defaults": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", @@ -3088,6 +11584,16 @@ "isobject": "^3.0.1" } }, + "object.reduce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", + "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -3112,34 +11618,67 @@ "wordwrap": "~0.0.2" } }, - "orchestrator": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", - "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", + "ordered-read-streams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", "dev": true, "requires": { - "end-of-stream": "~0.1.5", - "sequencify": "~0.0.7", - "stream-consume": "~0.1.0" + "readable-stream": "^2.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, - "ordered-read-streams": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", - "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", - "dev": true - }, "os-browserify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.1.2.tgz", "integrity": "sha1-ScoCk+CxlZCl9d4Qx/JlphfY/lQ=", "dev": true }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "^1.0.0" + } }, "pako": { "version": "0.2.9", @@ -3157,14 +11696,13 @@ } }, "parse-asn1": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz", - "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", "dev": true, "requires": { - "asn1.js": "^4.0.0", + "asn1.js": "^5.2.0", "browserify-aes": "^1.0.0", - "create-hash": "^1.1.0", "evp_bytestokey": "^1.0.0", "pbkdf2": "^3.0.3", "safe-buffer": "^5.1.1" @@ -3181,6 +11719,15 @@ "path-root": "^0.1.1" } }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, "parse-node-version": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", @@ -3205,6 +11752,21 @@ "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", "dev": true }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -3244,10 +11806,21 @@ "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", "dev": true }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, "pbkdf2": { - "version": "3.0.17", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", - "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", + "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", "dev": true, "requires": { "create-hash": "^1.1.2", @@ -3257,6 +11830,27 @@ "sha.js": "^2.4.8" } }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", @@ -3293,6 +11887,35 @@ "parse-asn1": "^5.0.0", "randombytes": "^2.0.1", "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" } }, "punycode": { @@ -3332,6 +11955,27 @@ "safe-buffer": "^5.1.0" } }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, "readable-stream": { "version": "1.1.14", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", @@ -3353,6 +11997,55 @@ "readable-stream": "^1.1.13-1" } }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", @@ -3363,11 +12056,12 @@ }, "dependencies": { "resolve": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", - "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", "dev": true, "requires": { + "is-core-module": "^2.2.0", "path-parse": "^1.0.6" } } @@ -3381,8 +12075,110 @@ "requires": { "extend-shallow": "^3.0.2", "safe-regex": "^1.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "remove-bom-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" + } + }, + "remove-bom-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", + "dev": true, + "requires": { + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + } } }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, "repeat-element": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", @@ -3401,6 +12197,29 @@ "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", "dev": true }, + "replace-homedir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", + "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1", + "is-absolute": "^1.0.0", + "remove-trailing-separator": "^1.1.0" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, "resolve": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.7.4.tgz", @@ -3417,6 +12236,15 @@ "global-modules": "^1.0.0" } }, + "resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", + "dev": true, + "requires": { + "value-or-function": "^3.0.0" + } + }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -3447,15 +12275,6 @@ } } }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, - "requires": { - "align-text": "^0.1.1" - } - }, "rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", @@ -3466,9 +12285,9 @@ }, "dependencies": { "glob": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.5.tgz", - "integrity": "sha512-J9dlskqUXK1OeTOYBEn5s8aMukWMwWfs+rPTn/jn50Ux4MNXVhubL1wu/j2t+H4NVI+cXEcCaYellqaPVGXNqQ==", + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -3532,9 +12351,9 @@ } }, "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true }, "safe-regex": { @@ -3546,16 +12365,31 @@ "ret": "~0.1.10" } }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, "semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true }, - "sequencify": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", - "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", + "semver-greatest-satisfied-range": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", + "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", + "dev": true, + "requires": { + "sver-compat": "^1.5.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, "set-immediate-shim": { @@ -3574,17 +12408,6 @@ "is-extendable": "^0.1.1", "is-plain-object": "^2.0.3", "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } } }, "sha.js": { @@ -3661,16 +12484,58 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } } }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" } }, "source-map": { @@ -3700,35 +12565,6 @@ "requires": { "is-descriptor": "^1.0.0" } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } } } }, @@ -3762,12 +12598,12 @@ } }, "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", "dev": true, "requires": { - "atob": "^2.1.1", + "atob": "^2.1.2", "decode-uri-component": "^0.2.0", "resolve-url": "^0.2.1", "source-map-url": "^0.4.0", @@ -3775,9 +12611,9 @@ } }, "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", "dev": true }, "sparkles": { @@ -3786,6 +12622,38 @@ "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", "dev": true }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz", + "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==", + "dev": true + }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -3793,8 +12661,35 @@ "dev": true, "requires": { "extend-shallow": "^3.0.0" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } } }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "dev": true + }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -3813,6 +12708,57 @@ "requires": { "is-descriptor": "^0.1.0" } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } } } }, @@ -3860,10 +12806,16 @@ } } }, - "stream-consume": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", - "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==", + "stream-exhaust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", + "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", + "dev": true + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", "dev": true }, "stream-splicer": { @@ -3886,6 +12838,17 @@ "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", @@ -3896,12 +12859,11 @@ } }, "strip-bom": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", - "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { - "first-chunk-stream": "^1.0.0", "is-utf8": "^0.2.0" } }, @@ -3920,6 +12882,16 @@ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true }, + "sver-compat": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", + "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", + "dev": true, + "requires": { + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } + }, "syntax-error": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", @@ -3999,13 +12971,68 @@ } } }, - "tildify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", - "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "through2-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", + "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", "dev": true, "requires": { - "os-homedir": "^1.0.0" + "through2": "~2.0.0", + "xtend": "~4.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + } } }, "time-stamp": { @@ -4031,6 +13058,16 @@ } } }, + "to-absolute-glob": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + } + }, "to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", @@ -4046,33 +13083,117 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", + "dev": true, + "requires": { + "through2": "^2.0.3" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true } } }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, "traverse": { "version": "0.6.6", "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", @@ -4085,6 +13206,12 @@ "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", "dev": true }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -4092,32 +13219,9 @@ "dev": true }, "uglify-js": { - "version": "2.4.24", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.24.tgz", - "integrity": "sha1-+tV1XB4Vd2WLsG/5q25UjJW+vW4=", - "dev": true, - "requires": { - "async": "~0.2.6", - "source-map": "0.1.34", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.5.4" - }, - "dependencies": { - "source-map": { - "version": "0.1.34", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.34.tgz", - "integrity": "sha1-p8/omux7FoLDsZjQrPtH19CQVms=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, - "uglify-save-license": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/uglify-save-license/-/uglify-save-license-0.4.1.tgz", - "integrity": "sha1-lXJsF8xv0XHDYX479NjYKqjEzOE=", + "version": "3.12.8", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.12.8.tgz", + "integrity": "sha512-fvBeuXOsvqjecUtF/l1dwsrrf5y2BCUk9AOJGzGcm6tE7vegku5u/YvqjyDaAGr422PLoLnrxg3EnRvTqsdC1w==", "dev": true }, "uglify-to-browserify": { @@ -4136,6 +13240,59 @@ "ruglify": "~1.0.0", "through": "~2.3.4", "uglify-js": "~2.4.0" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "source-map": { + "version": "0.1.34", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.34.tgz", + "integrity": "sha1-p8/omux7FoLDsZjQrPtH19CQVms=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + }, + "uglify-js": { + "version": "2.4.24", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.24.tgz", + "integrity": "sha1-+tV1XB4Vd2WLsG/5q25UjJW+vW4=", + "dev": true, + "requires": { + "async": "~0.2.6", + "source-map": "0.1.34", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.5.4" + } + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + }, + "yargs": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.5.4.tgz", + "integrity": "sha1-2K/49mXpTDS9JZvevRv68N3TU2E=", + "dev": true, + "requires": { + "camelcase": "^1.0.2", + "decamelize": "^1.0.0", + "window-size": "0.1.0", + "wordwrap": "0.0.2" + } + } } }, "unc-path-regex": { @@ -4144,6 +13301,30 @@ "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", "dev": true }, + "undertaker": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", + "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "fast-levenshtein": "^1.0.0", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + } + }, + "undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", + "dev": true + }, "union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", @@ -4157,10 +13338,14 @@ } }, "unique-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", - "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", - "dev": true + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", + "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", + "dev": true, + "requires": { + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "^3.0.0" + } }, "unset-value": { "version": "1.0.0", @@ -4208,6 +13393,12 @@ } } }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true + }, "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", @@ -4238,12 +13429,6 @@ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, - "user-home": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", - "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", - "dev": true - }, "util": { "version": "0.10.4", "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", @@ -4268,23 +13453,38 @@ "dev": true }, "v8flags": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", - "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, "requires": { - "user-home": "^1.1.1" + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" } }, + "value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", + "dev": true + }, "vinyl": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", - "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", "dev": true, "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" + "clone": "^0.2.0", + "clone-stats": "^0.0.1" } }, "vinyl-buffer": { @@ -4304,9 +13504,9 @@ "dev": true }, "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -4352,57 +13552,106 @@ } }, "vinyl-fs": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", - "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", - "dev": true, - "requires": { - "defaults": "^1.0.0", - "glob-stream": "^3.1.5", - "glob-watcher": "^0.0.6", - "graceful-fs": "^3.0.0", - "mkdirp": "^0.5.0", - "strip-bom": "^1.0.0", - "through2": "^0.6.1", - "vinyl": "^0.4.0" + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "requires": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" }, "dependencies": { "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "dev": true + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" } }, "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" } }, "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", + "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", "dev": true, "requires": { - "clone": "^0.2.0", - "clone-stats": "^0.0.1" + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" } }, "xtend": { @@ -4414,19 +13663,25 @@ } }, "vinyl-source-stream": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-1.1.2.tgz", - "integrity": "sha1-YrU6E1YQqJbpjKlr7jqH8Aio54A=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-2.0.0.tgz", + "integrity": "sha1-84pa+53R6Ttl1VBGmsYYKsT1S44=", "dev": true, "requires": { "through2": "^2.0.3", - "vinyl": "^0.4.3" + "vinyl": "^2.1.0" }, "dependencies": { "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", "dev": true }, "isarray": { @@ -4436,9 +13691,9 @@ "dev": true }, "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -4450,6 +13705,12 @@ "util-deprecate": "~1.0.1" } }, + "replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "dev": true + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -4476,13 +13737,17 @@ } }, "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", + "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", "dev": true, "requires": { - "clone": "^0.2.0", - "clone-stats": "^0.0.1" + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" } }, "xtend": { @@ -4493,6 +13758,79 @@ } } }, + "vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", + "dev": true, + "requires": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + }, + "dependencies": { + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "dev": true + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "vinyl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", + "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + } + } + }, "vinyl-sourcemaps-apply": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", @@ -4528,6 +13866,12 @@ "isexe": "^2.0.0" } }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, "window-size": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", @@ -4540,6 +13884,16 @@ "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", "dev": true }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -4552,6 +13906,12 @@ "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", "dev": true }, + "y18n": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", + "dev": true + }, "yamlish": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/yamlish/-/yamlish-0.0.7.tgz", @@ -4559,23 +13919,34 @@ "dev": true }, "yargs": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.5.4.tgz", - "integrity": "sha1-2K/49mXpTDS9JZvevRv68N3TU2E=", - "dev": true, - "requires": { - "camelcase": "^1.0.2", - "decamelize": "^1.0.0", - "window-size": "0.1.0", - "wordwrap": "0.0.2" - }, - "dependencies": { - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true - } + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.1.tgz", + "integrity": "sha512-huO4Fr1f9PmiJJdll5kwoS2e4GqzGSsMT3PPMpOwoVkOK8ckqAewMTZyA6LXVQWflleb/Z8oPBEvNsMft0XE+g==", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "5.0.0-security.0" + } + }, + "yargs-parser": { + "version": "5.0.0-security.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0-security.0.tgz", + "integrity": "sha512-T69y4Ps64LNesYxeYGYPvfoMTt/7y1XtfpIslUeK4um+9Hu7hlGoRtaDLvdXb7+/tfq4opVa2HRY5xGip022rQ==", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "object.assign": "^4.1.0" } } } diff --git a/package.json b/package.json index fd9b792..b5f1155 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "scripts": { "start": "gulp", "test": "tap test/*.js", - "release": "gulp release" + "release": "gulp release", + "build": "gulp release" }, "repository": { "type": "git", @@ -23,15 +24,14 @@ "devDependencies": { "browserify": "^8.0.3", "del": "^1.1.1", - "gulp": "^3.9.0", - "gulp-rename": "^1.2.0", - "gulp-run": "^1.6.5", - "gulp-uglify": "^1.0.2", - "gulp-util": "^3.0.2", + "gulp": "^4.0.2", + "gulp-rename": "^2.0.0", + "gulp-run": "^1.7.1", + "gulp-uglify": "^3.0.2", "ngraph.remove-overlaps": "^1.0.0", "tap": "^0.4.13", - "vinyl-buffer": "^1.0.0", - "vinyl-source-stream": "^1.0.0" + "vinyl-buffer": "^1.0.1", + "vinyl-source-stream": "^2.0.0" }, "dependencies": { "gintersect": "0.1.0", From 96287ddf3e1371003b50ef1b6f73d40651660ad0 Mon Sep 17 00:00:00 2001 From: Andriy Kashcha Date: Sat, 27 Feb 2021 10:31:23 -0800 Subject: [PATCH 263/276] Reverse the sign It should be negative to match common zooming behavior --- src/Input/dragndrop.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Input/dragndrop.js b/src/Input/dragndrop.js index 087fcaf..b0044b0 100644 --- a/src/Input/dragndrop.js +++ b/src/Input/dragndrop.js @@ -130,7 +130,7 @@ function dragndrop(element) { } e.returnValue = false; - var delta = e.deltaY, + var delta = -e.deltaY, mousePos = getMousePos(e), elementOffset = findElementPosition(element), relMousePos = { From 601c05ca8837e59cd7b037516314732d86c53a55 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 25 Jul 2021 15:28:22 -0700 Subject: [PATCH 264/276] Moved to github actions --- .github/workflows/tests.yaml | 26 ++++++++++++++++++++++++++ .travis.yml | 3 --- README.md | 2 +- 3 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/tests.yaml delete mode 100644 .travis.yml diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml new file mode 100644 index 0000000..87a91c6 --- /dev/null +++ b/.github/workflows/tests.yaml @@ -0,0 +1,26 @@ +name: Node.js CI + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [12.x, 14.x, 15.x] + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node-version }} + - run: npm ci + - run: npm run build --if-present + - run: npm test \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 851fb95..0000000 --- a/.travis.yml +++ /dev/null @@ -1,3 +0,0 @@ -language: node_js -node_js: -- node diff --git a/README.md b/README.md index 7e2e304..99b481c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -VivaGraph [![Build Status](https://travis-ci.org/anvaka/VivaGraphJS.svg)](https://travis-ci.org/anvaka/VivaGraphJS) +VivaGraph [![build status](https://github.com/anvaka/VivaGraphJS/actions/workflows/tests.yaml/badge.svg)](https://github.com/anvaka/VivaGraphJS/actions/workflows/tests.yaml) ================================================== **VivaGraphJS** is designed to be extensible and to support different rendering engines and layout algorithms. Underlying algorithms have been broken out into [ngraph](https://github.com/anvaka/ngraph). From 2ce9b403871554c6cb7ca53ac589985179eb4fa2 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 3 Apr 2022 20:23:50 -0700 Subject: [PATCH 265/276] updated years --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index f0cc9c2..e690758 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2011 - 2021, Andrei Kashcha +Copyright (c) 2011 - 2022, Andrei Kashcha All rights reserved. Redistribution and use in source and binary forms, with or without From b479e27a7e225b89d9327ad296a4ae9c2ad393d0 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 18 Jun 2023 14:37:31 -0700 Subject: [PATCH 266/276] updated year --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index e690758..a43161f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2011 - 2022, Andrei Kashcha +Copyright (c) 2011 - 2023, Andrei Kashcha All rights reserved. Redistribution and use in source and binary forms, with or without From 362ef05bdee6f8cc216602bf167b4379d49418b6 Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 13 Dec 2023 19:17:18 -0800 Subject: [PATCH 267/276] npm audit fix --- package-lock.json | 261 +++++++++++++++++++++++++--------------------- 1 file changed, 142 insertions(+), 119 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1f62af6..c77c766 100644 --- a/package-lock.json +++ b/package-lock.json @@ -629,9 +629,9 @@ } }, "node_modules/bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", "dev": true }, "node_modules/brace-expansion": { @@ -674,7 +674,7 @@ "node_modules/browser-pack": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-3.2.0.tgz", - "integrity": "sha1-+qHLxBSHsazEdH43PhFIrf/Q4tk=", + "integrity": "sha512-BHla5EbbxjNyLMFUMamVjeTY+q1QwHbrYNXlWOkw71QcBqAQF7maJyNh3OI/V0d5YyNdMYD6tiPhJB9ukBo99Q==", "dev": true, "dependencies": { "combine-source-map": "~0.3.0", @@ -728,7 +728,7 @@ "node_modules/browserify": { "version": "8.1.3", "resolved": "https://registry.npmjs.org/browserify/-/browserify-8.1.3.tgz", - "integrity": "sha1-8zpUmjpsNoIZsHX9z+bfGV4Empo=", + "integrity": "sha512-0KKOkCQXCvP64qm73CtESE92pVnB5MkjA2W/Tmf+S4uPHVY4/SeCwO7wdr4mkke5ySoVyMqsOcMa5zo6uh9c9A==", "dev": true, "dependencies": { "assert": "~1.3.0", @@ -833,26 +833,29 @@ } }, "node_modules/browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.2.tgz", + "integrity": "sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg==", "dev": true, "dependencies": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", + "bn.js": "^5.2.1", + "browserify-rsa": "^4.1.0", "create-hash": "^1.2.0", "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", + "elliptic": "^6.5.4", "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" + "parse-asn1": "^5.1.6", + "readable-stream": "^3.6.2", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 4" } }, "node_modules/browserify-sign/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "dependencies": { "inherits": "^2.0.3", @@ -928,7 +931,7 @@ "node_modules/bunker": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/bunker/-/bunker-0.1.2.tgz", - "integrity": "sha1-yImSRkqOKm7ehpMDdfkrWAd++Xw=", + "integrity": "sha512-YnahkcXBNT522S46k5LUA9P18lzvgkunbMl0qIJQ8oeRMQ+dAg3YI3k32q5TnO+AAUErFHO6R768To6jslgYmQ==", "dev": true, "dependencies": { "burrito": ">=0.2.5 <0.3" @@ -940,7 +943,7 @@ "node_modules/burrito": { "version": "0.2.12", "resolved": "https://registry.npmjs.org/burrito/-/burrito-0.2.12.tgz", - "integrity": "sha1-0NbmrIHV6ZeJxvpKzLCwAx6lT2s=", + "integrity": "sha512-ZhhT5iVTAgzQ+s8rily7m45Swxe/cU3dVCHTzqmHVWD/cc0Ds3W4Q4MExbkevY+fm0Me3lEwpehIy6TH7p+ehw==", "dev": true, "dependencies": { "traverse": "~0.5.1", @@ -962,7 +965,7 @@ "node_modules/burrito/node_modules/uglify-js": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-1.1.1.tgz", - "integrity": "sha1-7nGpfEzv0GoamyBDfzQRiYKqA1s=", + "integrity": "sha512-YYY9Dle1leC+btgrHnAR05eq0aRdcPJsXlYYD+SYw2lqc5HFuFNHg3wWEW4SNE0iXXEUl0fz43gTQ3r1YK76rg==", "dev": true, "bin": { "uglifyjs": "bin/uglifyjs" @@ -1367,13 +1370,22 @@ } }, "node_modules/copy-props": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", - "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", + "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", "dev": true, "dependencies": { - "each-props": "^1.3.0", - "is-plain-object": "^2.0.1" + "each-props": "^1.3.2", + "is-plain-object": "^5.0.0" + } + }, + "node_modules/copy-props/node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, "node_modules/core-util-is": { @@ -1485,9 +1497,9 @@ } }, "node_modules/decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", "dev": true, "engines": { "node": ">=0.10" @@ -2372,7 +2384,7 @@ "node_modules/glob": { "version": "4.5.3", "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", - "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "integrity": "sha512-I0rTWUKSZKxPSIAIaqhSXTM/DiII6wame+rEC3cFA5Lqmr9YmdL7z6Hj9+bdWtTvoY1Su4/OiMLmb37Y7JzvJQ==", "dev": true, "dependencies": { "inflight": "^1.0.4", @@ -2387,7 +2399,7 @@ "node_modules/glob-parent": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", "dev": true, "dependencies": { "is-glob": "^3.1.0", @@ -2409,7 +2421,7 @@ "node_modules/glob-stream": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", + "integrity": "sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw==", "dev": true, "dependencies": { "extend": "^3.0.0", @@ -2454,9 +2466,9 @@ "dev": true }, "node_modules/glob-stream/node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" @@ -3117,9 +3129,9 @@ } }, "node_modules/hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "node_modules/http-browserify": { @@ -4190,7 +4202,7 @@ "node_modules/minimatch": { "version": "2.0.10", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "integrity": "sha512-jQo6o1qSVLEWaw3l+bwYA2X0uLuK2KjNh2wjgO7Q/9UJnXr1Q3yQKR8BI0/Bt/rPg75e6SMW4hW/6cBHVTZUjA==", "deprecated": "Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue", "dev": true, "dependencies": { @@ -4201,10 +4213,13 @@ } }, "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/mixin-deep": { "version": "1.3.2", @@ -4987,9 +5002,9 @@ "dev": true }, "node_modules/path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "node_modules/path-platform": { @@ -5604,9 +5619,9 @@ } }, "node_modules/rimraf/node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" @@ -5628,7 +5643,7 @@ "node_modules/ruglify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/ruglify/-/ruglify-1.0.0.tgz", - "integrity": "sha1-3Ikw4qlUSidDAcyZcldMDQmGtnU=", + "integrity": "sha512-XfRj1YJdm/gnZNvmpQ5L+2YGRHglDGMPgJRbitgCxC3GzKVQF/t+ij1aNcNg2AnEXGtLHJDwoSWrAq3TUm0EVg==", "dev": true, "dependencies": { "rfile": "~1.0", @@ -5638,7 +5653,7 @@ "node_modules/ruglify/node_modules/uglify-js": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.2.5.tgz", - "integrity": "sha1-puAqcNg5eSuXgEiLe4sYTAlcmcc=", + "integrity": "sha512-viLk+/8G0zm2aKt1JJAVcz5J/5ytdiNaIsKgrre3yvSUjwVG6ZUujGH7E2TiPigZUwLYCe7eaIUEP2Zka2VJPA==", "dev": true, "dependencies": { "optimist": "~0.3.5", @@ -5654,7 +5669,7 @@ "node_modules/runforcover": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/runforcover/-/runforcover-0.0.2.tgz", - "integrity": "sha1-NE8FfY1F0zrrxsyCIEZ49pxIV8w=", + "integrity": "sha512-yarCIK2HcAOadqnKW419+FA38qpWDCKcOr5RZU+jnyLL/hn3No9BHZY+YJDEzvQ0k8Oyl7ffLjZv9ZUxvyKoLQ==", "dev": true, "dependencies": { "bunker": "0.1.X" @@ -5699,9 +5714,9 @@ "dev": true }, "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, "bin": { "semver": "bin/semver" @@ -5781,7 +5796,7 @@ "node_modules/shell-quote": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-0.0.1.tgz", - "integrity": "sha1-GkEZbzwDM8SCMjWT1ohuzxU92YY=", + "integrity": "sha512-uEWz7wa9vnCi9w4mvKZMgbHFk3DCKjLQlZcy0tJxUH4NwZjRrPPHXAYIEt2TmJs600Dcgj0Z3fZLZKVPVdGNbQ==", "dev": true, "engines": { "node": "*" @@ -6319,7 +6334,7 @@ "node_modules/tap": { "version": "0.4.13", "resolved": "https://registry.npmjs.org/tap/-/tap-0.4.13.tgz", - "integrity": "sha1-OYYTTWdZcn/CIj5hEm7rhyQ6zLw=", + "integrity": "sha512-DRPT9T2qqeUQ9nC8nwnZPQQnKA+bVhzaNrIDoFETFqWLXGOvil/JMhuWj5uO6XeNzIdvvPKLqPHQzIkJnjNnDQ==", "dev": true, "dependencies": { "buffer-equal": "~0.0.0", @@ -6352,7 +6367,7 @@ "node_modules/tap/node_modules/glob": { "version": "3.2.11", "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", - "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "integrity": "sha512-hVb0zwEZwC1FXSKRPFTeOtN7AArJcJlI6ULGLtrstaswKNlrTJqAA+1lYlSUop4vjA423xlBzqfVS3iWGlqJ+g==", "dev": true, "dependencies": { "inherits": "2", @@ -6365,7 +6380,7 @@ "node_modules/tap/node_modules/minimatch": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", - "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "integrity": "sha512-WFX1jI1AaxNTZVOHLBVazwTWKaQjoykSzCBNXB72vDTCzopQGtyP91tKdFK5cv1+qMwPyiTu1HqUriqplI8pcA==", "deprecated": "Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue", "dev": true, "dependencies": { @@ -6698,7 +6713,7 @@ "node_modules/umd": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/umd/-/umd-2.1.0.tgz", - "integrity": "sha1-SmMHt2LxfwLSAbX6FU5nM5bCY88=", + "integrity": "sha512-mEAJeceExHnblcAwN3BQtDPYOrTy4ALeBh6nQ9KW0cUCd0UU714jAfil2jvq09b67IizwJIiTVFOjE+/52Dyvw==", "dev": true, "dependencies": { "rfile": "~1.0.0", @@ -6740,7 +6755,7 @@ "node_modules/umd/node_modules/uglify-js": { "version": "2.4.24", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.24.tgz", - "integrity": "sha1-+tV1XB4Vd2WLsG/5q25UjJW+vW4=", + "integrity": "sha512-tktIjwackfZLd893KGJmXc1hrRHH1vH9Po3xFh1XBjjeGAnN02xJ3SuoA+n1L29/ZaCA18KzCFlckS+vfPugiA==", "dev": true, "dependencies": { "async": "~0.2.6", @@ -8005,9 +8020,9 @@ } }, "bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", "dev": true }, "brace-expansion": { @@ -8047,7 +8062,7 @@ "browser-pack": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-3.2.0.tgz", - "integrity": "sha1-+qHLxBSHsazEdH43PhFIrf/Q4tk=", + "integrity": "sha512-BHla5EbbxjNyLMFUMamVjeTY+q1QwHbrYNXlWOkw71QcBqAQF7maJyNh3OI/V0d5YyNdMYD6tiPhJB9ukBo99Q==", "dev": true, "requires": { "combine-source-map": "~0.3.0", @@ -8102,7 +8117,7 @@ "browserify": { "version": "8.1.3", "resolved": "https://registry.npmjs.org/browserify/-/browserify-8.1.3.tgz", - "integrity": "sha1-8zpUmjpsNoIZsHX9z+bfGV4Empo=", + "integrity": "sha512-0KKOkCQXCvP64qm73CtESE92pVnB5MkjA2W/Tmf+S4uPHVY4/SeCwO7wdr4mkke5ySoVyMqsOcMa5zo6uh9c9A==", "dev": true, "requires": { "assert": "~1.3.0", @@ -8204,26 +8219,26 @@ } }, "browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.2.tgz", + "integrity": "sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg==", "dev": true, "requires": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", + "bn.js": "^5.2.1", + "browserify-rsa": "^4.1.0", "create-hash": "^1.2.0", "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", + "elliptic": "^6.5.4", "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" + "parse-asn1": "^5.1.6", + "readable-stream": "^3.6.2", + "safe-buffer": "^5.2.1" }, "dependencies": { "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "requires": { "inherits": "^2.0.3", @@ -8297,7 +8312,7 @@ "bunker": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/bunker/-/bunker-0.1.2.tgz", - "integrity": "sha1-yImSRkqOKm7ehpMDdfkrWAd++Xw=", + "integrity": "sha512-YnahkcXBNT522S46k5LUA9P18lzvgkunbMl0qIJQ8oeRMQ+dAg3YI3k32q5TnO+AAUErFHO6R768To6jslgYmQ==", "dev": true, "requires": { "burrito": ">=0.2.5 <0.3" @@ -8306,7 +8321,7 @@ "burrito": { "version": "0.2.12", "resolved": "https://registry.npmjs.org/burrito/-/burrito-0.2.12.tgz", - "integrity": "sha1-0NbmrIHV6ZeJxvpKzLCwAx6lT2s=", + "integrity": "sha512-ZhhT5iVTAgzQ+s8rily7m45Swxe/cU3dVCHTzqmHVWD/cc0Ds3W4Q4MExbkevY+fm0Me3lEwpehIy6TH7p+ehw==", "dev": true, "requires": { "traverse": "~0.5.1", @@ -8322,7 +8337,7 @@ "uglify-js": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-1.1.1.tgz", - "integrity": "sha1-7nGpfEzv0GoamyBDfzQRiYKqA1s=", + "integrity": "sha512-YYY9Dle1leC+btgrHnAR05eq0aRdcPJsXlYYD+SYw2lqc5HFuFNHg3wWEW4SNE0iXXEUl0fz43gTQ3r1YK76rg==", "dev": true } } @@ -8665,13 +8680,21 @@ "dev": true }, "copy-props": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", - "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", + "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", "dev": true, "requires": { - "each-props": "^1.3.0", - "is-plain-object": "^2.0.1" + "each-props": "^1.3.2", + "is-plain-object": "^5.0.0" + }, + "dependencies": { + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true + } } }, "core-util-is": { @@ -8776,9 +8799,9 @@ "dev": true }, "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", "dev": true }, "deep-equal": { @@ -9552,7 +9575,7 @@ "glob": { "version": "4.5.3", "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", - "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "integrity": "sha512-I0rTWUKSZKxPSIAIaqhSXTM/DiII6wame+rEC3cFA5Lqmr9YmdL7z6Hj9+bdWtTvoY1Su4/OiMLmb37Y7JzvJQ==", "dev": true, "requires": { "inflight": "^1.0.4", @@ -9564,7 +9587,7 @@ "glob-parent": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", "dev": true, "requires": { "is-glob": "^3.1.0", @@ -9585,7 +9608,7 @@ "glob-stream": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", + "integrity": "sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw==", "dev": true, "requires": { "extend": "^3.0.0", @@ -9621,9 +9644,9 @@ "dev": true }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -10201,9 +10224,9 @@ } }, "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "http-browserify": { @@ -11104,16 +11127,16 @@ "minimatch": { "version": "2.0.10", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "integrity": "sha512-jQo6o1qSVLEWaw3l+bwYA2X0uLuK2KjNh2wjgO7Q/9UJnXr1Q3yQKR8BI0/Bt/rPg75e6SMW4hW/6cBHVTZUjA==", "dev": true, "requires": { "brace-expansion": "^1.0.0" } }, "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true }, "mixin-deep": { @@ -11780,9 +11803,9 @@ "dev": true }, "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "path-platform": { @@ -12299,9 +12322,9 @@ } }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -12322,7 +12345,7 @@ "ruglify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/ruglify/-/ruglify-1.0.0.tgz", - "integrity": "sha1-3Ikw4qlUSidDAcyZcldMDQmGtnU=", + "integrity": "sha512-XfRj1YJdm/gnZNvmpQ5L+2YGRHglDGMPgJRbitgCxC3GzKVQF/t+ij1aNcNg2AnEXGtLHJDwoSWrAq3TUm0EVg==", "dev": true, "requires": { "rfile": "~1.0", @@ -12332,7 +12355,7 @@ "uglify-js": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.2.5.tgz", - "integrity": "sha1-puAqcNg5eSuXgEiLe4sYTAlcmcc=", + "integrity": "sha512-viLk+/8G0zm2aKt1JJAVcz5J/5ytdiNaIsKgrre3yvSUjwVG6ZUujGH7E2TiPigZUwLYCe7eaIUEP2Zka2VJPA==", "dev": true, "requires": { "optimist": "~0.3.5", @@ -12344,7 +12367,7 @@ "runforcover": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/runforcover/-/runforcover-0.0.2.tgz", - "integrity": "sha1-NE8FfY1F0zrrxsyCIEZ49pxIV8w=", + "integrity": "sha512-yarCIK2HcAOadqnKW419+FA38qpWDCKcOr5RZU+jnyLL/hn3No9BHZY+YJDEzvQ0k8Oyl7ffLjZv9ZUxvyKoLQ==", "dev": true, "requires": { "bunker": "0.1.X" @@ -12372,9 +12395,9 @@ "dev": true }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true }, "semver-greatest-satisfied-range": { @@ -12439,7 +12462,7 @@ "shell-quote": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-0.0.1.tgz", - "integrity": "sha1-GkEZbzwDM8SCMjWT1ohuzxU92YY=", + "integrity": "sha512-uEWz7wa9vnCi9w4mvKZMgbHFk3DCKjLQlZcy0tJxUH4NwZjRrPPHXAYIEt2TmJs600Dcgj0Z3fZLZKVPVdGNbQ==", "dev": true }, "sigmund": { @@ -12904,7 +12927,7 @@ "tap": { "version": "0.4.13", "resolved": "https://registry.npmjs.org/tap/-/tap-0.4.13.tgz", - "integrity": "sha1-OYYTTWdZcn/CIj5hEm7rhyQ6zLw=", + "integrity": "sha512-DRPT9T2qqeUQ9nC8nwnZPQQnKA+bVhzaNrIDoFETFqWLXGOvil/JMhuWj5uO6XeNzIdvvPKLqPHQzIkJnjNnDQ==", "dev": true, "requires": { "buffer-equal": "~0.0.0", @@ -12928,7 +12951,7 @@ "glob": { "version": "3.2.11", "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", - "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "integrity": "sha512-hVb0zwEZwC1FXSKRPFTeOtN7AArJcJlI6ULGLtrstaswKNlrTJqAA+1lYlSUop4vjA423xlBzqfVS3iWGlqJ+g==", "dev": true, "requires": { "inherits": "2", @@ -12938,7 +12961,7 @@ "minimatch": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", - "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "integrity": "sha512-WFX1jI1AaxNTZVOHLBVazwTWKaQjoykSzCBNXB72vDTCzopQGtyP91tKdFK5cv1+qMwPyiTu1HqUriqplI8pcA==", "dev": true, "requires": { "lru-cache": "2", @@ -13233,7 +13256,7 @@ "umd": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/umd/-/umd-2.1.0.tgz", - "integrity": "sha1-SmMHt2LxfwLSAbX6FU5nM5bCY88=", + "integrity": "sha512-mEAJeceExHnblcAwN3BQtDPYOrTy4ALeBh6nQ9KW0cUCd0UU714jAfil2jvq09b67IizwJIiTVFOjE+/52Dyvw==", "dev": true, "requires": { "rfile": "~1.0.0", @@ -13266,7 +13289,7 @@ "uglify-js": { "version": "2.4.24", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.24.tgz", - "integrity": "sha1-+tV1XB4Vd2WLsG/5q25UjJW+vW4=", + "integrity": "sha512-tktIjwackfZLd893KGJmXc1hrRHH1vH9Po3xFh1XBjjeGAnN02xJ3SuoA+n1L29/ZaCA18KzCFlckS+vfPugiA==", "dev": true, "requires": { "async": "~0.2.6", From 0d4d50a48c8e39c3bb4b2d5abbca158c7e158075 Mon Sep 17 00:00:00 2001 From: anvaka Date: Thu, 14 Dec 2023 20:01:35 -0800 Subject: [PATCH 268/276] rebuild --- dist/vivagraph.js | 20 +++----------------- dist/vivagraph.min.js | 4 +--- 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/dist/vivagraph.js b/dist/vivagraph.js index 8124757..727b7a2 100644 --- a/dist/vivagraph.js +++ b/dist/vivagraph.js @@ -3881,7 +3881,7 @@ function dragndrop(element) { } e.returnValue = false; - var delta, + var delta = -e.deltaY, mousePos = getMousePos(e), elementOffset = findElementPosition(element), relMousePos = { @@ -3889,29 +3889,15 @@ function dragndrop(element) { y: mousePos[1] - elementOffset[1] }; - if (e.wheelDelta) { - delta = e.wheelDelta / 360; // Chrome/Safari - } else { - delta = e.detail / -9; // Mozilla - } - scroll(e, delta, relMousePos); }, updateScrollEvents = function (scrollCallback) { if (!scroll && scrollCallback) { // client is interested in scrolling. Start listening to events: - if (browserInfo.browser === 'webkit') { - element.addEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari - } else { - element.addEventListener('DOMMouseScroll', handleMouseWheel, false); // Others - } + element.addEventListener('wheel', handleMouseWheel, false); } else if (scroll && !scrollCallback) { - if (browserInfo.browser === 'webkit') { - element.removeEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari - } else { - element.removeEventListener('DOMMouseScroll', handleMouseWheel, false); // Others - } + element.removeEventListener('wheel', handleMouseWheel, false); } scroll = scrollCallback; diff --git a/dist/vivagraph.min.js b/dist/vivagraph.min.js index 6872ddd..b73a6f0 100644 --- a/dist/vivagraph.min.js +++ b/dist/vivagraph.min.js @@ -1,3 +1 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e()}}(function(){return function e(n,t,r){function o(a,u){if(!t[a]){if(!n[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=t[a]={exports:{}};n[a][0].call(c.exports,function(e){var t=n[a][1][e];return o(t?t:e)},c,c.exports,e,n,t,r)}return t[a].exports}for(var i="function"==typeof require&&require,a=0;a=0==m>=4?null:(f=u-i,d=o-a,p=a*i-o*u,v=f*e+d*n+p,h=f*t+d*r+p,0!==v&&0!==h&&v>=0==h>=0?null:(y=s*d-f*c,0===y?null:(x=y<0?-y/2:y/2,x=0,w=c*p-d*l,b.x=(w<0?w-x:w+x)/y,w=f*l-s*p,b.y=(w<0?w-x:w+x)/y,b)))}n.exports=r},{}],4:[function(e,n,t){n.exports.degree=e("./src/degree.js"),n.exports.betweenness=e("./src/betweenness.js"),n.exports.closeness=e("./src/closeness.js"),n.exports.eccentricity=e("./src/eccentricity.js")},{"./src/betweenness.js":5,"./src/closeness.js":6,"./src/degree.js":7,"./src/eccentricity.js":8}],5:[function(e,n,t){function r(e,n){function t(e){h[e]/=2}function r(e){h[e.id]=0}function o(e){s=e.id,u(s),i()}function i(){for(e.forEachNode(a);c.length;){for(var n=c.pop(),t=(1+v[n])/p[n],r=d[n],o=0;o0?f[a]=(n-1)/t:f[a]=0}function i(t){function r(e){var n=e.id;s[n]=-1}function o(e){var n=e.id;s[n]===-1&&(s[n]=s[i]+1,u.push(n))}for(e.forEachNode(r),s[t]=0,u.push(t);u.length;){var i=u.shift();e.forEachLinkedNode(i,o,n)}}var a,u=[],s=Object.create(null),f=Object.create(null);return e.forEachNode(t),e.forEachNode(r),f}n.exports=r},{}],7:[function(e,n,t){function r(e,n){function t(n){var t=e.getLinks(n.id);u[n.id]=r(t,n.id)}var r,u=Object.create(null);if(n=(n||"both").toLowerCase(),"both"===n||"inout"===n)r=a;else if("in"===n)r=o;else{if("out"!==n)throw new Error("Expected centrality degree kind is: in, out or both");r=i}return e.forEachNode(t),u}function o(e,n){var t=0;if(!e)return t;for(var r=0;r1&&(o=Array.prototype.splice.call(arguments,1));for(var i=0;i0&&i.addLink(a,r-1+o*e),o>0&&i.addLink(a,r+(o-1)*e)}return i}function s(e,t,r){if(e<1||t<1||r<1)throw new Error("Invalid number of nodes in grid3 graph");var o,i,a,u=n();if(1===e&&1===t&&1===r)return u.addNode(0),u;for(a=0;a0&&u.addLink(f,o-1+i*e+s),i>0&&u.addLink(f,o+(i-1)*e+s),a>0&&u.addLink(f,o+i*e+(a-1)*e*t)}return u}function f(e){if(e<0)throw new Error("Invalid number of nodes in balanced tree");var t,r=n(),o=Math.pow(2,e);for(0===e&&r.addNode(1),t=1;t= 0");var t,r=n();for(t=0;t0&&o.addLink(i*t,i*t-1);return o.addLink(0,o.getNodesCount()-1),o}function l(t,r,o,i){if(r>=t)throw new Error("Choose smaller `k`. It cannot be larger than number of nodes `n`");var a,u,s=e("ngraph.random").random(i||42),f=n();for(a=0;a=1||0===e);return n*Math.sqrt(-2*Math.log(e)/e)}function a(){var e=this.seed;return e=e+2127912214+(e<<12)&4294967295,e=4294967295&(3345072700^e^e>>>19),e=e+374761393+(e<<5)&4294967295,e=4294967295&(e+3550635116^e<<9),e=e+4251993797+(e<<3)&4294967295,e=4294967295&(3042594569^e^e>>>16),this.seed=e,(268435455&e)/268435456}function u(e){return Math.floor(this.nextDouble()*e)}function s(e,n){function t(){var n,t,r;for(n=e.length-1;n>0;--n)t=i.next(n+1),r=e[t],e[t]=e[n],e[n]=r;return e}function o(n){var t,r,o;for(t=e.length-1;t>0;--t)r=i.next(t+1),o=e[r],e[r]=e[t],e[t]=o,n(o);e.length&&n(e[0])}var i=n||r();if("function"!=typeof i.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:o,shuffle:t}}n.exports=r,n.exports.random=r,n.exports.randomIterator=s,o.prototype.next=u,o.prototype.nextDouble=a,o.prototype.uniform=a,o.prototype.gaussian=i},{}],16:[function(e,n,t){function r(e){function n(){function e(){return q.beginUpdate=F=k,q.endUpdate=G=P,B=t,O=r,q.on=n,n.apply(q,arguments)}var n=q.on;q.on=e}function t(e,n){R.push({link:e,changeType:n})}function r(e,n){R.push({node:e,changeType:n})}function c(e,n){if(void 0===e)throw new Error("Invalid node identifier");F();var t=d(e);return t?(t.data=n,O(t,"update")):(t=new i(e,n),S++,O(t,"add")),I[e]=t,G(),t}function d(e){return I[e]}function l(e){var n=d(e);if(!n)return!1;F();var t=n.links;if(t){n.links=null;for(var r=0;r=0&&t.links.splice(n,1)),r&&(n=o(e,r.links),n>=0&&r.links.splice(n,1)),B(e,"remove"),G(),!0}function y(e,n){var t,r=d(e);if(!r||!r.links)return null;for(t=0;t0&&(q.fire("changed",R),R.length=0)}function j(){return Object.keys?A:_}function A(e){if("function"==typeof e)for(var n=Object.keys(I),t=0;t=0?i:-1,o);return v.push(a),a},getTotalMovement:function(){return w},removeSpring:function(e){if(e){var n=v.indexOf(e);return n>-1?(v.splice(n,1),!0):void 0}},getBestNewBodyPosition:function(e){return g.getBestNewPosition(e)},getBBox:function(){return x&&(g.update(),x=!1),g.box},invalidateBBox:function(){x=!0},gravity:function(e){return void 0!==e?(n.gravity=e,h.options({gravity:e}),this):n.gravity},theta:function(e){return void 0!==e?(n.theta=e,h.options({theta:e}),this):n.theta}};return o(n,b),a(b),b}n.exports=r},{"./lib/bounds":20,"./lib/createBody":21,"./lib/dragForce":22,"./lib/eulerIntegrator":23,"./lib/spring":24,"./lib/springForce":25,"ngraph.events":9,"ngraph.expose":10,"ngraph.merge":17,"ngraph.quadtreebh":26}],20:[function(e,n,t){n.exports=function(n,t){function r(){var e=n.length;if(0!==e){for(var t=Number.MAX_VALUE,r=Number.MAX_VALUE,o=Number.MIN_VALUE,a=Number.MIN_VALUE;e--;){var u=n[e];u.isPinned?(u.pos.x=u.prevPos.x,u.pos.y=u.prevPos.y):(u.prevPos.x=u.pos.x,u.prevPos.y=u.pos.y),u.pos.xo&&(o=u.pos.x),u.pos.ya&&(a=u.pos.y)}i.x1=t,i.x2=o,i.y1=r,i.y2=a}}var o=e("ngraph.random").random(42),i={x1:0,y1:0,x2:0,y2:0};return{box:i,update:r,reset:function(){i.x1=i.y1=0,i.x2=i.y2=0},getBestNewPosition:function(e){var n=i,r=0,a=0;if(e.length){for(var u=0;u1&&(s.velocity.x=c/l,s.velocity.y=d/l),r=n*s.velocity.x,i=n*s.velocity.y,s.pos.x+=r,s.pos.y+=i,o+=Math.abs(r),a+=Math.abs(i)}return(o*o+a*a)/u}n.exports=r},{}],24:[function(e,n,t){function r(e,n,t,r,o){this.from=e,this.to=n,this.length=t,this.coeff=r,this.weight="number"==typeof o?o:1}n.exports=r},{}],25:[function(e,n,t){n.exports=function(n){var t=e("ngraph.merge"),r=e("ngraph.random").random(42),o=e("ngraph.expose");n=t(n,{springCoeff:2e-4,springLength:80});var i={update:function(e){var t=e.from,o=e.to,i=e.length<0?n.springLength:e.length,a=o.pos.x-t.pos.x,u=o.pos.y-t.pos.y,s=Math.sqrt(a*a+u*u);0===s&&(a=(r.nextDouble()-.5)/50,u=(r.nextDouble()-.5)/50,s=Math.sqrt(a*a+u*u));var f=s-i,c=(!e.coeff||e.coeff<0?n.springCoeff:e.coeff)*f/s*e.weight;t.force.x+=c*a,t.force.y+=c*u,o.force.x-=c*a,o.force.y-=c*u}};return o(n,i,["springCoeff","springLength"]),i}},{"ngraph.expose":10,"ngraph.merge":17,"ngraph.random":30}],26:[function(e,n,t){function r(e,n){return 0===n?e.quad0:1===n?e.quad1:2===n?e.quad2:3===n?e.quad3:null}function o(e,n,t){0===n?e.quad0=t:1===n?e.quad1=t:2===n?e.quad2=t:3===n&&(e.quad3=t)}n.exports=function(n){function t(){var e=g[m];return e?(e.quad0=null,e.quad1=null,e.quad2=null,e.quad3=null,e.body=null,e.mass=e.massX=e.massY=0,e.left=e.right=e.top=e.bottom=0):(e=new f,g[m]=e),++m,e}function i(e){var n,t,r,o,i=p,a=0,u=0,f=1,c=0,d=1;for(i[0]=y;f;){var v=i[c],g=v.body;f-=1,c+=1;var m=g!==e;g&&m?(t=g.pos.x-e.pos.x,r=g.pos.y-e.pos.y,o=Math.sqrt(t*t+r*r),0===o&&(t=(s.nextDouble()-.5)/50,r=(s.nextDouble()-.5)/50,o=Math.sqrt(t*t+r*r)),n=l*g.mass*e.mass/(o*o*o),a+=n*t,u+=n*r):m&&(t=v.massX/v.mass-e.pos.x,r=v.massY/v.mass-e.pos.y,o=Math.sqrt(t*t+r*r),0===o&&(t=(s.nextDouble()-.5)/50,r=(s.nextDouble()-.5)/50,o=Math.sqrt(t*t+r*r)),(v.right-v.left)/oi&&(i=f),ca&&(a=c)}var d=i-r,l=a-o;for(d>l?a=o+d:i=r+l,m=0,y=t(),y.left=r,y.right=i,y.top=o,y.bottom=a,n=s-1,n>=0&&(y.body=e[n]);n--;)u(e[n],y)}function u(e){for(v.reset(),v.push(y,e);!v.isEmpty();){var n=v.pop(),i=n.node,a=n.body;if(i.body){var u=i.body;if(i.body=null,d(u.pos,a.pos)){var f=3;do{var c=s.nextDouble(),l=(i.right-i.left)*c,p=(i.bottom-i.top)*c;u.pos.x=i.left+l,u.pos.y=i.top+p,f-=1}while(f>0&&d(u.pos,a.pos));if(0===f&&d(u.pos,a.pos))return}v.push(i,u),v.push(i,a)}else{var h=a.pos.x,g=a.pos.y;i.mass=i.mass+a.mass,i.massX=i.massX+a.mass*h,i.massY=i.massY+a.mass*g;var m=0,x=i.left,w=(i.right+x)/2,b=i.top,E=(i.bottom+b)/2;h>w&&(m+=1,x=w,w=i.right),g>E&&(m+=2,b=E,E=i.bottom);var L=r(i,m);L?v.push(L,a):(L=t(),L.left=x,L.top=b,L.right=w,L.bottom=E,L.body=a,o(i,m,L))}}}n=n||{},n.gravity="number"==typeof n.gravity?n.gravity:-1,n.theta="number"==typeof n.theta?n.theta:.8;var s=e("ngraph.random").random(1984),f=e("./node"),c=e("./insertStack"),d=e("./isSamePosition"),l=n.gravity,p=[],v=new c,h=n.theta,g=[],m=0,y=t();return{insertBodies:a,getRoot:function(){return y},updateBodyForce:i,options:function(e){return e?("number"==typeof e.gravity&&(l=e.gravity),"number"==typeof e.theta&&(h=e.theta),this):{gravity:l,theta:h}}}}},{"./insertStack":27,"./isSamePosition":28,"./node":29,"ngraph.random":30}],27:[function(e,n,t){function r(){this.stack=[],this.popIdx=0}function o(e,n){this.node=e,this.body=n}n.exports=r,r.prototype={isEmpty:function(){return 0===this.popIdx},push:function(e,n){var t=this.stack[this.popIdx];t?(t.node=e,t.body=n):this.stack[this.popIdx]=new o(e,n),++this.popIdx},pop:function(){if(this.popIdx>0)return this.stack[--this.popIdx]},reset:function(){this.popIdx=0}}},{}],28:[function(e,n,t){n.exports=function(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return t<1e-8&&r<1e-8}},{}],29:[function(e,n,t){n.exports=function(){this.body=null,this.quad0=null,this.quad1=null,this.quad2=null,this.quad3=null,this.mass=0,this.massX=0,this.massY=0,this.left=0,this.top=0,this.bottom=0,this.right=0}},{}],30:[function(e,n,t){function r(e){var n="number"==typeof e?e:+new Date,t=function(){return n=n+2127912214+(n<<12)&4294967295,n=4294967295&(3345072700^n^n>>>19),n=n+374761393+(n<<5)&4294967295,n=4294967295&(n+3550635116^n<<9),n=n+4251993797+(n<<3)&4294967295,n=4294967295&(3042594569^n^n>>>16),(268435455&n)/268435456};return{next:function(e){return Math.floor(t()*e)},nextDouble:function(){return t()}}}function o(e,n){var t=n||r();if("function"!=typeof t.next)throw new Error("customRandom does not match expected API: next() function is missing");return{forEach:function(n){var r,o,i;for(r=e.length-1;r>0;--r)o=t.next(r+1),i=e[o],e[o]=e[r],e[r]=i,n(i);e.length&&n(e[0])},shuffle:function(){var n,r,o;for(n=e.length-1;n>0;--n)r=t.next(n+1),o=e[r],e[r]=e[n],e[n]=o;return e}}}n.exports={random:r,randomIterator:o}},{}],31:[function(e,n,t){function r(e,n,t){function r(e){u.nodes.push(s(e))}function o(e){u.links.push(f(e))}function i(e){var n={id:e.id};return void 0!==e.data&&(n.data=e.data),n}function a(e){var n={fromId:e.fromId,toId:e.toId};return void 0!==e.data&&(n.data=e.data),n}var u={nodes:[],links:[]},s=n||i,f=t||a;return e.forEachNode(r),e.forEachLink(o),JSON.stringify(u)}n.exports=r},{}],32:[function(e,n,t){function r(e,n){var t=o(e);if(void 0===n)return t;for(var r=Object.keys(n),i=0;iv&&(r=1),u(e,r,{x:e.touches[0].clientX,y:e.touches[0].clientY}),v=t,m(e),y(e)}},j=function(e){p=!1,o.off("touchmove",P),o.off("touchend",j),o.off("touchcancel",j),c=null,r&&r(e)},A=function(e,t){m(e),y(e),d=t.clientX,l=t.clientY,c=e.target||e.srcElement,n&&n(e,{x:d,y:l}),p||(p=!0,o.on("touchmove",P),o.on("touchend",j),o.on("touchcancel",j))},_=function(e){return 1===e.touches.length?A(e,e.touches[0]):void(2===e.touches.length&&(m(e),y(e),v=k(e.touches[0],e.touches[1])))};return e.addEventListener("mousedown",b),e.addEventListener("touchstart",_),{onStart:function(e){return n=e,this},onDrag:function(e){return t=e,this},onStop:function(e){return r=e,this},onScroll:function(e){return N(e),this},release:function(){e.removeEventListener("mousedown",b),e.removeEventListener("touchstart",_),o.off("mousemove",w),o.off("mouseup",E),o.off("touchmove",P),o.off("touchend",j),o.off("touchcancel",j),N(null)}}}n.exports=r;var o=e("../Utils/documentEvents.js"),i=e("../Utils/browserInfo.js"),a=e("../Utils/findElementPosition.js")},{"../Utils/browserInfo.js":43,"../Utils/documentEvents.js":44,"../Utils/findElementPosition.js":45}],40:[function(e,n,t){function r(e,n){var t=o(n),r=null,i={},a={x:0,y:0};return t.mouseDown(function(e,n){r=e,a.x=n.clientX,a.y=n.clientY,t.mouseCapture(r);var o=i[e.id];return o&&o.onStart&&o.onStart(n,a),!0}).mouseUp(function(e){t.releaseMouseCapture(r),r=null;var n=i[e.id];return n&&n.onStop&&n.onStop(),!0}).mouseMove(function(e,n){if(r){var t=i[r.id];return t&&t.onDrag&&t.onDrag(n,{x:n.clientX-a.x,y:n.clientY-a.y}),a.x=n.clientX,a.y=n.clientY,!0}}),{bindDragNDrop:function(e,n){i[e.id]=n,n||delete i[e.id]}}}n.exports=r;var o=e("../WebGL/webglInputEvents.js")},{"../WebGL/webglInputEvents.js":61}],41:[function(e,n,t){function r(e,n){function t(e){return d[e]}n=o(n,{maxX:1024,maxY:1024,seed:"Deterministic randomness made me do this"});var r=i(n.seed),u=new a(Number.MAX_VALUE,Number.MAX_VALUE,Number.MIN_VALUE,Number.MIN_VALUE),s={},f=function(e){return{x:r.next(n.maxX),y:r.next(n.maxY)}},c=function(e,n){e.xn.x2&&(n.x2=e.x),e.yn.y2&&(n.y2=e.y)},d="function"==typeof Object.create?Object.create(null):{},l=function(e){d[e.id]=f(e),c(d[e.id],u)},p=function(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(l))},v=function(e){s[e.id]=e},h=function(e){for(var n=0;n=0:"boolean"!=typeof q||q}function r(){G=G||window.document.body,O=O||i(e,{springLength:80,springCoeff:2e-4}),F=F||a(e,{container:G}),n.hasOwnProperty("renderLinks")||(n.renderLinks=!0),n.prerender=n.prerender||0,U=(F.inputManager||s)(e,F)}function l(){F.beginRender(),n.renderLinks&&F.renderLinks(),F.renderNodes(),F.endRender()}function p(){return X=O.step()&&!V,l(),!X}function v(e){R||(R=void 0!==e?f(function(){if(e-=1,e<0){var n=!1;return n}return p()},M):f(p,M))}function h(){W||(X=!1,R.restart())}function g(){if("number"==typeof n.prerender&&n.prerender>0)for(var e=0;e0?n.insertBefore(r,n.firstChild):n.appendChild(r),r},releaseLink:function(e){var t=d[e.id];t&&(n.removeChild(t),delete d[e.id])},addNode:function(e,t){var r=l(e);if(r)return r.position=t,r.node=e,c[e.id]=r,n.appendChild(r),r},releaseNode:function(e){var t=c[e.id];t&&(n.removeChild(t),delete c[e.id])},renderNodes:function(){for(var e in c)if(c.hasOwnProperty(e)){var n=c[e];m.x=n.position.x,m.y=n.position.y,p(n,m,n.node)}},renderLinks:function(){for(var e in d)if(d.hasOwnProperty(e)){var n=d[e];y.x=n.position.from.x,y.y=n.position.from.y,x.x=n.position.to.x,x.y=n.position.to.y,h(n,y,x,n.link)}},getGraphicsRoot:function(e){return"function"==typeof e&&(t?e(t):r=e),t},getSvgRoot:function(){return t}};return i(b),b}n.exports=r;var o=e("simplesvg"),i=e("ngraph.events"),a=e("../Input/domInputManager.js")},{"../Input/domInputManager.js":38,"ngraph.events":9,simplesvg:32}],54:[function(e,n,t){function r(e){e=c(e,{enableBlending:!0,preserveDrawingBuffer:!1,clearColor:!1,clearColorValue:{r:1,g:1,b:1,a:1}});var n,t,r,d,l,p,v,h,g=0,m=0,y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],x=[],w=[],b={},E={},L=i(),N=a(),k=function(e){return u()},P=function(e){return s(3014898687)},j=function(){L.updateTransform(y),N.updateTransform(y)},A=function(){y=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]},_=function(){n&&t&&(d=t.width=Math.max(n.offsetWidth,1),l=t.height=Math.max(n.offsetHeight,1),r&&r.viewport(0,0,d,l),L&&L.updateSize(d/2,l/2),N&&N.updateSize(d/2,l/2))},I=function(e){e.fire("rescaled")};t=window.document.createElement("canvas");var T={getLinkUI:function(e){return E[e]},getNodeUI:function(e){return b[e]},node:function(e){if("function"==typeof e)return k=e,this},link:function(e){if("function"==typeof e)return P=e,this},placeNode:function(e){return p=e,this},placeLink:function(e){return v=e,this},inputManager:o,beginRender:function(){},endRender:function(){m>0&&L.render(),g>0&&N.render()},bringLinkToFront:function(e){var n,t,r=L.getFrontLinkId();L.bringToFront(e),r>e.id&&(n=e.id,t=w[r],w[r]=w[n],w[r].id=r,w[n]=t,w[n].id=n)},graphCenterChanged:function(e,n){y[12]=2*e/d-1,y[13]=1-2*n/l,j()},addLink:function(e,n){var t=m++,r=P(e);return r.id=t,r.pos=n,L.createLink(r),w[t]=r,E[e.id]=r,r},addNode:function(e,n){var t=g++,r=k(e);return r.id=t,r.position=n,r.node=e,N.createNode(r),x[t]=r,b[e.id]=r,r},translateRel:function(e,n){y[12]+=2*y[0]*e/d/y[0],y[13]-=2*y[5]*n/l/y[5],j()},scale:function(e,n){var t=2*n.x/d-1,r=1-2*n.y/l;return t-=y[12],r-=y[13],y[12]+=t*(1-e),y[13]+=r*(1-e),y[0]*=e,y[5]*=e,j(),I(this),y[0]},resetScale:function(){return A(),r&&(_(),j()),this},updateSize:_,init:function(o){var i={};if(e.preserveDrawingBuffer&&(i.preserveDrawingBuffer=!0),n=o,_(),A(),n.appendChild(t),r=t.getContext("experimental-webgl",i),!r){var a="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(a),a}if(e.enableBlending&&(r.blendFunc(r.SRC_ALPHA,r.ONE_MINUS_SRC_ALPHA),r.enable(r.BLEND)),e.clearColor){var u=e.clearColorValue;r.clearColor(u.r,u.g,u.b,u.a),this.beginRender=function(){r.clear(r.COLOR_BUFFER_BIT)}}L.load(r),L.updateSize(d/2,l/2),N.load(r),N.updateSize(d/2,l/2),j(),"function"==typeof h&&h(t)},release:function(e){t&&e&&e.removeChild(t)},isSupported:function(){var e=window.document.createElement("canvas"),n=e&&e.getContext&&e.getContext("experimental-webgl");return n},releaseLink:function(e){m>0&&(m-=1);var n=E[e.id];delete E[e.id],L.removeLink(n);var t=n.id;if(t0&&(g-=1);var n=b[e.id];delete b[e.id],N.removeNode(n);var t=n.id;if(te.length){var r=new Float32Array(e.length*t*2);return r.set(e),r}return e}function a(n,t){for(var r={},o=0;o=w.length&&s();var i=w[r.textureNumber];i.ctx.drawImage(n,r.col*g,r.row*g,g,g),b[e]=n.src,y[n.src]=o,i.isDirty=!0,t(o)}function c(n){var t=n/e<<0,r=n%e,o=r/h<<0,i=r%h;return{textureNumber:t,row:o,col:i}}function d(){E.isDirty=!0,x=0,v=null}function l(){v&&(window.clearTimeout(v),x+=1,v=null),x>10?d():v=window.setTimeout(d,400)}function p(e,n){var t=w[e.textureNumber].canvas,r=w[n.textureNumber].ctx,o=n.col*g,i=n.row*g;r.drawImage(t,e.col*g,e.row*g,g,g,o,i,g,g),w[e.textureNumber].isDirty=!0,w[n.textureNumber].isDirty=!0}var v,h=Math.sqrt(e||1024)<<0,g=h,m=1,y={},x=0,w=[],b=[];if(!o(e))throw"Tiles per texture should be power of two.";var E={isDirty:!1,clearDirty:n,remove:t,getTextures:r,getCoordinates:a,load:u};return E}function o(e){return 0===(e&e-1)}var i=e("./texture.js");n.exports=r},{"./texture.js":56}],59:[function(e,n,t){function r(e,n){return{_texture:0,_offset:0,size:"number"==typeof e?e:32,src:n}}n.exports=r},{}],60:[function(e,n,t){function r(e){function n(e,n){e.nativeObject&&m.deleteTexture(e.nativeObject);var t=m.createTexture();m.activeTexture(m["TEXTURE"+n]),m.bindTexture(m.TEXTURE_2D,t),m.texImage2D(m.TEXTURE_2D,0,m.RGBA,m.RGBA,m.UNSIGNED_BYTE,e.canvas),m.texParameteri(m.TEXTURE_2D,m.TEXTURE_MAG_FILTER,m.LINEAR),m.texParameteri(m.TEXTURE_2D,m.TEXTURE_MIN_FILTER,m.LINEAR_MIPMAP_NEAREST),m.generateMipmap(m.TEXTURE_2D),m.uniform1i(w["sampler"+n],n),e.nativeObject=t}function t(){if(h.isDirty){var e,t=h.getTextures();for(e=0;e0&&(A-=1),e.id0&&(e.src&&h.remove(e.src),x.copyArrayPart(_,e.id*k,A*k,k))}function d(e,n){n._offset=e._offset}function l(e){N=!0,L=e}function p(e,n){b=e,E=n,N=!0}function v(){m.useProgram(g),m.bindBuffer(m.ARRAY_BUFFER,y),m.bufferData(m.ARRAY_BUFFER,_,m.DYNAMIC_DRAW),N&&(N=!1,m.uniformMatrix4fv(w.transform,!1,L),m.uniform2f(w.screenSize,b,E)),m.vertexAttribPointer(w.vertexPos,2,m.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),m.vertexAttribPointer(w.customAttributes,1,m.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,8),t(),m.drawArrays(m.TRIANGLES,0,6*A)}var h,g,m,y,x,w,b,E,L,N,k=18,P=o(),j=i(),e=e||1024,A=0,_=new Float32Array(64);return{load:r,position:s,createNode:f,removeNode:c,replaceProperties:d,updateTransform:l,updateSize:p,render:v}}function o(){return["precision mediump float;","varying vec4 color;","varying vec3 vTextureCoord;","uniform sampler2D u_sampler0;","uniform sampler2D u_sampler1;","uniform sampler2D u_sampler2;","uniform sampler2D u_sampler3;","void main(void) {"," if (vTextureCoord.z == 0.) {"," gl_FragColor = texture2D(u_sampler0, vTextureCoord.xy);"," } else if (vTextureCoord.z == 1.) {"," gl_FragColor = texture2D(u_sampler1, vTextureCoord.xy);"," } else if (vTextureCoord.z == 2.) {"," gl_FragColor = texture2D(u_sampler2, vTextureCoord.xy);"," } else if (vTextureCoord.z == 3.) {"," gl_FragColor = texture2D(u_sampler3, vTextureCoord.xy);"," } else { gl_FragColor = vec4(0, 1, 0, 1); }","}"].join("\n")}function i(){return["attribute vec2 a_vertexPos;","attribute float a_customAttributes;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","uniform float u_tilesPerTexture;","varying vec3 vTextureCoord;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos/u_screenSize, 0, 1);","float corner = mod(a_customAttributes, 4.);","float tileIndex = mod(floor(a_customAttributes / 4.), u_tilesPerTexture);","float tilesPerRow = sqrt(u_tilesPerTexture);","float tileSize = 1./tilesPerRow;","float tileColumn = mod(tileIndex, tilesPerRow);","float tileRow = floor(tileIndex/tilesPerRow);","if(corner == 0.0) {"," vTextureCoord.xy = vec2(0, 1);","} else if(corner == 1.0) {"," vTextureCoord.xy = vec2(1, 1);","} else if(corner == 2.0) {"," vTextureCoord.xy = vec2(0, 0);","} else {"," vTextureCoord.xy = vec2(1, 0);","}","vTextureCoord *= tileSize;","vTextureCoord.x += tileColumn * tileSize;","vTextureCoord.y += tileRow * tileSize;","vTextureCoord.z = floor(floor(a_customAttributes / 4.)/u_tilesPerTexture);","}"].join("\n")}var a=e("./webglAtlas.js"),u=e("./webgl.js");n.exports=r},{"./webgl.js":57,"./webglAtlas.js":58}],61:[function(e,n,t){function r(e){function n(){x=null}function t(e){x=e}function r(e){return"function"==typeof e&&P.push(e),A}function i(e){return"function"==typeof e&&k.push(e),A}function a(e){return"function"==typeof e&&N.push(e),A}function u(e){return"function"==typeof e&&L.push(e),A}function s(e){return"function"==typeof e&&E.push(e),A}function f(e){return"function"==typeof e&&b.push(e),A}function c(e){return"function"==typeof e&&w.push(e),A}function d(e,n,t){if(e&&e.size){var r=e.position,o=e.size;return r.x-og.byteLength){var e=new ArrayBuffer(2*g.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(y),m=n,y=t,g=e}};return{load:function(a){n=a,r=o(a),e=r.createProgram(v,p),n.useProgram(e),i=r.getLocations(e,["a_vertexPos","a_color","u_screenSize","u_transform"]),n.enableVertexAttribArray(i.vertexPos),n.enableVertexAttribArray(i.color),t=n.createBuffer()},position:function(e,n,t){var r=e.id,o=r*d;m[o]=n.x,m[o+1]=n.y,y[o+2]=e.color,m[o+3]=t.x,m[o+4]=t.y,y[o+5]=e.color},createLink:function(e){x(),h+=1,a=e.id},removeLink:function(e){h>0&&(h-=1),e.id0&&r.copyArrayPart(y,e.id*d,h*d,d)},updateTransform:function(e){c=!0,f=e},updateSize:function(e,n){u=e,s=n,c=!0},render:function(){n.useProgram(e),n.bindBuffer(n.ARRAY_BUFFER,t),n.bufferData(n.ARRAY_BUFFER,g,n.DYNAMIC_DRAW),c&&(c=!1,n.uniformMatrix4fv(i.transform,!1,f),n.uniform2f(i.screenSize,u,s)),n.vertexAttribPointer(i.vertexPos,2,n.FLOAT,!1,3*Float32Array.BYTES_PER_ELEMENT,0),n.vertexAttribPointer(i.color,4,n.UNSIGNED_BYTE,!0,3*Float32Array.BYTES_PER_ELEMENT,8),n.drawArrays(n.LINES,0,2*h),a=h-1},bringToFront:function(e){a>e.id&&r.swapArrayPart(m,e.id*d,a*d,d),a>0&&(a-=1)},getFrontLinkId:function(){return a}}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":57}],64:[function(e,n,t){function r(){function e(){if((P+1)*w>=L.byteLength){var e=new ArrayBuffer(2*L.byteLength),n=new Float32Array(e),t=new Uint32Array(e);t.set(k),N=n,k=t,L=e}}function n(e){d=e,v=o(e),c=v.createProgram(E,b),d.useProgram(c), -p=v.getLocations(c,["a_vertexPos","a_color","u_screenSize","u_transform"]),d.enableVertexAttribArray(p.vertexPos),d.enableVertexAttribArray(p.color),l=d.createBuffer()}function t(e,n){var t=e.id;N[t*x]=n.x,N[t*x+1]=-n.y,N[t*x+2]=e.size,k[t*x+3]=e.color}function r(e){y=!0,m=e}function i(e,n){h=e,g=n,y=!0}function a(e){P>0&&(P-=1),e.id0&&v.copyArrayPart(k,e.id*x,P*x,x)}function u(){e(),P+=1}function s(){}function f(){d.useProgram(c),d.bindBuffer(d.ARRAY_BUFFER,l),d.bufferData(d.ARRAY_BUFFER,L,d.DYNAMIC_DRAW),y&&(y=!1,d.uniformMatrix4fv(p.transform,!1,m),d.uniform2f(p.screenSize,h,g)),d.vertexAttribPointer(p.vertexPos,3,d.FLOAT,!1,x*Float32Array.BYTES_PER_ELEMENT,0),d.vertexAttribPointer(p.color,4,d.UNSIGNED_BYTE,!0,x*Float32Array.BYTES_PER_ELEMENT,12),d.drawArrays(d.POINTS,0,P)}var c,d,l,p,v,h,g,m,y,x=4,w=3*Float32Array.BYTES_PER_ELEMENT+Uint32Array.BYTES_PER_ELEMENT,b=["precision mediump float;","varying vec4 color;","void main(void) {"," gl_FragColor = color;","}"].join("\n"),E=["attribute vec3 a_vertexPos;","attribute vec4 a_color;","uniform vec2 u_screenSize;","uniform mat4 u_transform;","varying vec4 color;","void main(void) {"," gl_Position = u_transform * vec4(a_vertexPos.xy/u_screenSize, 0, 1);"," gl_PointSize = a_vertexPos.z * u_transform[0][0];"," color = a_color.abgr;","}"].join("\n"),L=new ArrayBuffer(16*w),N=new Float32Array(L),k=new Uint32Array(L),P=0;return{load:n,position:t,updateTransform:r,updateSize:i,removeNode:a,createNode:u,replaceProperties:s,render:f}}var o=e("./webgl.js");n.exports=r},{"./webgl.js":57}],65:[function(e,n,t){function r(e,n){return{size:"number"==typeof e?e:10,color:o(n)}}var o=e("./parseColor.js");n.exports=r},{"./parseColor.js":55}],66:[function(e,n,t){n.exports="0.10.1"},{}]},{},[1])(1)}); \ No newline at end of file +!function(e){var n;"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):("undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.Viva=e())}(function(){return function r(o,i,a){function u(t,e){if(!i[t]){if(!o[t]){var n="function"==typeof require&&require;if(!e&&n)return n(t,!0);if(s)return s(t,!0);n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}n=i[t]={exports:{}};o[t][0].call(n.exports,function(e){var n=o[t][1][e];return u(n||e)},n,n.exports,r,o,i,a)}return i[t].exports}for(var s="function"==typeof require&&require,e=0;e= 0");var n,t=h();for(n=0;n>>19))+(e<<5)&4294967295)^e<<9))+(e<<3)&4294967295)^e>>>16),(268435455&(this.seed=e))/268435456}n.exports=r,n.exports.random=r,n.exports.randomIterator=function(o,e){var i=e||r();if("function"==typeof i.next)return{forEach:function(e){var n,t,r;for(n=o.length-1;0r&&(r=i.pos.x),i.pos.yo&&(o=i.pos.y)}s.x1=n,s.x2=r,s.y1=t,s.y2=o},reset:function(){s.x1=s.y1=0,s.x2=s.y2=0},getBestNewPosition:function(e){var n=s,t=0,r=0;if(e.length){for(var o=0;o>>19))+374761393+(t<<5)&4294967295)+3550635116^t<<9))+4251993797+(t<<3)&4294967295)^t>>>16)))/268435456}var t="number"==typeof e?e:+new Date;return{next:function(e){return Math.floor(n()*e)},nextDouble:n}}n.exports={random:r,randomIterator:function(o,e){var i=e||r();if("function"==typeof i.next)return{forEach:function(e){for(var n,t,r=o.length-1;0e.x2&&(e.x2=n.x),n.ye.y2&&(e.y2=n.y)}function t(){0!==e.getNodesCount()&&(u.x1=Number.MAX_VALUE,u.y1=Number.MAX_VALUE,u.x2=Number.MIN_VALUE,u.y2=Number.MIN_VALUE,e.forEachNode(r))}function o(e){s[e.id]=e}function i(e){for(var n=0;ne.id&&(n=e.id,e=x[t],x[t]=x[n],x[t].id=t,x[n]=e,x[n].id=n)},graphCenterChanged:function(e,n){m[12]=2*e/c-1,m[13]=1-2*n/d,o()},addLink:function(e,n){var t=v++,r=P(e);return r.id=t,r.pos=n,E.createLink(r),x[t]=r,b[e.id]=r},addNode:function(e,n){var t=g++,r=N(e);return r.id=t,r.position=n,r.node=e,L.createNode(r),y[t]=r,w[e.id]=r},translateRel:function(e,n){m[12]+=2*m[0]*e/c/m[0],m[13]-=2*m[5]*n/d/m[5],o()},scale:function(e,n){var t=2*n.x/c-1,n=1-2*n.y/d;return t-=m[12],n-=m[13],m[12]+=t*(1-e),m[13]+=n*(1-e),m[0]*=e,m[5]*=e,o(),this.fire("rescaled"),m[0]},resetScale:function(){return i(),f&&(a(),o()),this},updateSize:a,init:function(e){var n={};if(r.preserveDrawingBuffer&&(n.preserveDrawingBuffer=!0),u=e,a(),i(),u.appendChild(s),!(f=s.getContext("experimental-webgl",n))){var t="Could not initialize WebGL. Seems like the browser doesn't support it.";throw window.alert(t),t}r.enableBlending&&(f.blendFunc(f.SRC_ALPHA,f.ONE_MINUS_SRC_ALPHA),f.enable(f.BLEND)),r.clearColor&&(t=r.clearColorValue,f.clearColor(t.r,t.g,t.b,t.a),this.beginRender=function(){f.clear(f.COLOR_BUFFER_BIT)}),E.load(f),E.updateSize(c/2,d/2),L.load(f),L.updateSize(c/2,d/2),o(),"function"==typeof h&&h(s)},release:function(e){s&&e&&e.removeChild(s)},isSupported:function(){var e=window.document.createElement("canvas");return e&&e.getContext&&e.getContext("experimental-webgl")},releaseLink:function(e){0e.length){t=new Float32Array(e.length*t*2);return t.set(e),t}return e},copyArrayPart:o,swapArrayPart:i,getLocations:function(e,n){for(var t={},r=0;r=f.length&&function(){var e=new p(a*u);f.push(e)}();var i=f[r.textureNumber];i.ctx.drawImage(n,r.col*u,r.row*u,u,u),c[e]=n.src,s[n.src]=o,i.isDirty=!0,t(o)}(r,t,n)},t.src=e)}}};return r;function d(e){var n=e%t;return{textureNumber:e/t<<0,row:n/a<<0,col:n%a}}function i(){r.isDirty=!0,n=0,e=null}function l(){e&&(window.clearTimeout(e),n+=1,e=null),10g.byteLength&&(n=new ArrayBuffer(2*g.byteLength),t=new Float32Array(n),(r=new Uint32Array(n)).set(m),v=t,m=r,g=n),h+=1,a=e.id},removeLink:function(e){0e.id&&o.swapArrayPart(v,6*e.id,6*a,6),0=p.byteLength&&(e=new ArrayBuffer(2*p.byteLength),n=new Float32Array(e),(t=new Uint32Array(e)).set(g),h=n,g=t,p=e)})(),v+=1},replaceProperties:function(){},render:function(){t.useProgram(n),t.bindBuffer(t.ARRAY_BUFFER,r),t.bufferData(t.ARRAY_BUFFER,p,t.DYNAMIC_DRAW),f&&(f=!1,t.uniformMatrix4fv(o.transform,!1,s),t.uniform2f(o.screenSize,a,u));t.vertexAttribPointer(o.vertexPos,3,t.FLOAT,!1,4*Float32Array.BYTES_PER_ELEMENT,0),t.vertexAttribPointer(o.color,4,t.UNSIGNED_BYTE,!0,4*Float32Array.BYTES_PER_ELEMENT,12),t.drawArrays(t.POINTS,0,v)}}}},{"./webgl.js":57}],65:[function(e,n,t){var r=e("./parseColor.js");n.exports=function(e,n){return{size:"number"==typeof e?e:10,color:r(n)}}},{"./parseColor.js":55}],66:[function(e,n,t){n.exports="0.10.1"},{}]},{},[1])(1)}); \ No newline at end of file From 7b555ac1be9640ec42fa031ae26f03a77f362993 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sat, 20 Jan 2024 11:17:18 -0800 Subject: [PATCH 269/276] updated year --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index a43161f..84ac1b1 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2011 - 2023, Andrei Kashcha +Copyright (c) 2011 - 2024, Andrei Kashcha All rights reserved. Redistribution and use in source and binary forms, with or without From c1a68d3a1080cb530787571a0dbd59da9ea4f7a1 Mon Sep 17 00:00:00 2001 From: anvaka Date: Sun, 19 May 2024 22:24:54 -0700 Subject: [PATCH 270/276] npm audit fix --- package-lock.json | 115 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 91 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index c77c766..7b07b40 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1834,14 +1834,19 @@ } }, "node_modules/es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", "dev": true, + "hasInstallScript": true, "dependencies": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" } }, "node_modules/es6-iterator": { @@ -1886,6 +1891,37 @@ "node": ">=0.8.0" } }, + "node_modules/esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "dev": true, + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esniff/node_modules/type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==", + "dev": true + }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, "node_modules/events": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/events/-/events-1.0.2.tgz", @@ -2717,7 +2753,7 @@ "node_modules/gulp-run": { "version": "1.7.1", "resolved": "https://registry.npmjs.org/gulp-run/-/gulp-run-1.7.1.tgz", - "integrity": "sha1-4XwKy3wwtuKu7iPAREKpbAys7/o=", + "integrity": "sha512-4OcXhBE5xpRWmbcKzE0EQWEqpLRAkX3ju6k85qkYLfmnCVGK6nPmu/sbVgDiGg6mjuzsF2b9nHFbImZBZPH3zg==", "dev": true, "dependencies": { "gulp-util": "^3.0.0", @@ -2827,7 +2863,7 @@ "node_modules/gulp-util": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "integrity": "sha512-q5oWPc12lwSFS9h/4VIjG+1NuNDlJ48ywV2JKItY4Ycc/n1fXJeYPVQsfu5ZrhQi7FGSDBalwUCLar/GyHXKGw==", "deprecated": "gulp-util is deprecated - replace it, following the guidelines at https://medium.com/gulpjs/gulp-util-ca3b1f9f9ac5", "dev": true, "dependencies": { @@ -2872,7 +2908,7 @@ "node_modules/gulp-util/node_modules/lodash.template": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "integrity": "sha512-0B4Y53I0OgHUJkt+7RmlDFWKjVAI/YUpWNiL9GQz5ORDr4ttgfQGo+phBWKFLJbBdtOwgMuUkdOHOnPg45jKmQ==", "dev": true, "dependencies": { "lodash._basecopy": "^3.0.0", @@ -4427,9 +4463,9 @@ } }, "node_modules/next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", "dev": true }, "node_modules/ngraph.centrality": { @@ -9097,14 +9133,15 @@ } }, "es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", "dev": true, "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", + "next-tick": "^1.1.0" } }, "es6-iterator": { @@ -9146,6 +9183,36 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, + "esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "dev": true, + "requires": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "dependencies": { + "type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==", + "dev": true + } + } + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, "events": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/events/-/events-1.0.2.tgz", @@ -9862,7 +9929,7 @@ "gulp-run": { "version": "1.7.1", "resolved": "https://registry.npmjs.org/gulp-run/-/gulp-run-1.7.1.tgz", - "integrity": "sha1-4XwKy3wwtuKu7iPAREKpbAys7/o=", + "integrity": "sha512-4OcXhBE5xpRWmbcKzE0EQWEqpLRAkX3ju6k85qkYLfmnCVGK6nPmu/sbVgDiGg6mjuzsF2b9nHFbImZBZPH3zg==", "dev": true, "requires": { "gulp-util": "^3.0.0", @@ -9965,7 +10032,7 @@ "gulp-util": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "integrity": "sha512-q5oWPc12lwSFS9h/4VIjG+1NuNDlJ48ywV2JKItY4Ycc/n1fXJeYPVQsfu5ZrhQi7FGSDBalwUCLar/GyHXKGw==", "dev": true, "requires": { "array-differ": "^1.0.0", @@ -10003,7 +10070,7 @@ "lodash.template": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "integrity": "sha512-0B4Y53I0OgHUJkt+7RmlDFWKjVAI/YUpWNiL9GQz5ORDr4ttgfQGo+phBWKFLJbBdtOwgMuUkdOHOnPg45jKmQ==", "dev": true, "requires": { "lodash._basecopy": "^3.0.0", @@ -11306,9 +11373,9 @@ } }, "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", "dev": true }, "ngraph.centrality": { From c01c28fae14cc504292fcb005c55e71448b2d037 Mon Sep 17 00:00:00 2001 From: anvaka Date: Fri, 12 Jul 2024 22:18:34 -0700 Subject: [PATCH 271/276] npm audit fix --- package-lock.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7b07b40..0338632 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4083,7 +4083,7 @@ "node_modules/matchdep": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", - "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", + "integrity": "sha512-LFgVbaHIHMqCRuCZyfCtUOq9/Lnzhi7Z0KFUE2fhD54+JN2jLh3hC02RLkqauJ3U4soU6H1J3tfj/Byk7GoEjA==", "dev": true, "dependencies": { "findup-sync": "^2.0.0", @@ -4098,7 +4098,7 @@ "node_modules/matchdep/node_modules/findup-sync": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "integrity": "sha512-vs+3unmJT45eczmcAZ6zMJtxN3l/QXeccaXQx5cu/MeJMhewVfoWZqibRkOxPnmoR59+Zy5hjabfQc6JLSah4g==", "dev": true, "dependencies": { "detect-file": "^1.0.0", @@ -11060,7 +11060,7 @@ "matchdep": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", - "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", + "integrity": "sha512-LFgVbaHIHMqCRuCZyfCtUOq9/Lnzhi7Z0KFUE2fhD54+JN2jLh3hC02RLkqauJ3U4soU6H1J3tfj/Byk7GoEjA==", "dev": true, "requires": { "findup-sync": "^2.0.0", @@ -11072,7 +11072,7 @@ "findup-sync": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "integrity": "sha512-vs+3unmJT45eczmcAZ6zMJtxN3l/QXeccaXQx5cu/MeJMhewVfoWZqibRkOxPnmoR59+Zy5hjabfQc6JLSah4g==", "dev": true, "requires": { "detect-file": "^1.0.0", From 6373e7e83f1a878a8bfb9a7f15ed84825f62030b Mon Sep 17 00:00:00 2001 From: anvaka Date: Thu, 29 Aug 2024 20:14:52 -1000 Subject: [PATCH 272/276] updated node engines --- .github/workflows/tests.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 87a91c6..8d2f957 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -13,7 +13,7 @@ jobs: strategy: matrix: - node-version: [12.x, 14.x, 15.x] + node-version: [20.x, 18.x] steps: - uses: actions/checkout@v2 @@ -23,4 +23,4 @@ jobs: node-version: ${{ matrix.node-version }} - run: npm ci - run: npm run build --if-present - - run: npm test \ No newline at end of file + - run: npm test From b9a5238cf871103e9cbec042b075b71e7b8d35f0 Mon Sep 17 00:00:00 2001 From: anvaka Date: Thu, 7 Nov 2024 22:49:39 -0800 Subject: [PATCH 273/276] npm audit fix --- package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0338632..f8dbb9e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1795,9 +1795,9 @@ } }, "node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.0.tgz", + "integrity": "sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==", "dev": true, "dependencies": { "bn.js": "^4.11.9", @@ -9092,9 +9092,9 @@ } }, "elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.0.tgz", + "integrity": "sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==", "dev": true, "requires": { "bn.js": "^4.11.9", From 4a02fd479d57fa2e516463cc3bd0ca8be0136d62 Mon Sep 17 00:00:00 2001 From: anvaka Date: Fri, 7 Mar 2025 21:17:36 -0800 Subject: [PATCH 274/276] npm audit fix --- package-lock.json | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index f8dbb9e..71d2c09 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1795,10 +1795,11 @@ } }, "node_modules/elliptic": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.0.tgz", - "integrity": "sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==", + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", + "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", "dev": true, + "license": "MIT", "dependencies": { "bn.js": "^4.11.9", "brorand": "^1.1.0", @@ -9092,9 +9093,9 @@ } }, "elliptic": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.0.tgz", - "integrity": "sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==", + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", + "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", "dev": true, "requires": { "bn.js": "^4.11.9", From e67aa5a4b361e91ed00b4970313f9f2a6d949e18 Mon Sep 17 00:00:00 2001 From: anvaka Date: Wed, 23 Apr 2025 20:10:12 -0700 Subject: [PATCH 275/276] updated years --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 84ac1b1..cee6d40 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2011 - 2024, Andrei Kashcha +Copyright (c) 2011 - 2025, Andrei Kashcha All rights reserved. Redistribution and use in source and binary forms, with or without From e7d55f2405e2abeeee1cef236a195d1c063c9355 Mon Sep 17 00:00:00 2001 From: anvaka Date: Thu, 5 Mar 2026 23:34:32 -0800 Subject: [PATCH 276/276] updated year --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index cee6d40..1295245 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2011 - 2025, Andrei Kashcha +Copyright (c) 2011 - 2026, Andrei Kashcha All rights reserved. Redistribution and use in source and binary forms, with or without