(function (f) {
    if (typeof exports === "object" && typeof module !== "undefined") {
        module.exports = f()
    } else if (typeof define === "function" && define.amd) {
        define([], f)
    } else {
        var g;
        if (typeof window !== "undefined") {
            g = window
        } else if (typeof global !== "undefined") {
            g = global
        } else if (typeof self !== "undefined") {
            g = self
        } else {
            g = this
        }
        g.greuler = f()
    }
})(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 < r.length; o++) s(r[o]);
        return s
    })({
        1: [function (require, module, exports) {
            'use strict';
            module.exports = function (val) {
                if (val == null) {
                    return [];
                }

                return Array.isArray(val) ? val : [val];
            };

        }, {}],
        2: [function (require, module, exports) {

            'use strict';

// VARIABLES //

            var MASK = 123459876,
                M = 2147483647,
                A = 16807;


// LCG //

            /**
             * FUNCTION: lcg( [seed] )
             *    Returns a linear congruential pseudorandom number generator. If not provided a seed, a seed is generated based on the current time.
             *
             * @param {Number} [seed] - random number generator seed
             * @returns {Function} generator
             */
            function lcg(val) {
                var seed;
                if (arguments.length) {
                    if (typeof val !== 'number' || val !== val || val % 1 !== 0 || val < 1) {
                        throw new TypeError('lcg()::invalid input argument. Seed must be a positive integer.');
                    }
                    seed = val;
                } else {
                    seed = Date.now() % 100000000;
                }
                /**
                 * FUNCTION: lcg( [N] )
                 *    Linear congruential pseudorandom number generator.
                 *
                 * @param {Number} [N] - number of pseudorandom numbers to return
                 * @returns {Number|Array} pseudorandom floating-point number(s) between 0 and 1
                 */
                return function lcg(N) {
                    var arr,
                        rand;
                    if (!arguments.length) {
                        seed = seed ^ MASK;
                        seed = (A * seed) % M;
                        rand = seed / M;
                        seed = seed ^ MASK;
                        return rand;
                    }
                    if (typeof N !== 'number' || N !== N || N % 1 !== 0 || N < 1) {
                        throw new TypeError('lcg()::invalid input argument. Array length must be a positive integer.');
                    }
                    arr = new Array(N);
                    for (var i = 0; i < N; i++) {
                        seed = seed ^ MASK;
                        seed = (A * seed) % M;
                        arr[i] = seed / M;
                        seed = seed ^ MASK;
                    }
                    return arr;
                };
            } // end FUNCTION lcg()


// EXPORTS //

            module.exports = lcg;


        }, {}],
        3: [function (require, module, exports) {
            'use strict';

            var hasOwn = Object.prototype.hasOwnProperty;
            var toStr = Object.prototype.toString;

            var isArray = function isArray(arr) {
                if (typeof Array.isArray === 'function') {
                    return Array.isArray(arr);
                }

                return toStr.call(arr) === '[object Array]';
            };

            var isPlainObject = function isPlainObject(obj) {
                if (!obj || toStr.call(obj) !== '[object Object]') {
                    return false;
                }

                var hasOwnConstructor = hasOwn.call(obj, 'constructor');
                var hasIsPrototypeOf = obj.constructor && obj.constructor.prototype && hasOwn.call(obj.constructor.prototype, 'isPrototypeOf');
                // Not own constructor property must be Object
                if (obj.constructor && !hasOwnConstructor && !hasIsPrototypeOf) {
                    return false;
                }

                // Own properties are enumerated firstly, so to speed up,
                // if last one is own, then all properties are own.
                var key;
                for (key in obj) {/**/
                }

                return typeof key === 'undefined' || hasOwn.call(obj, key);
            };

            module.exports = function extend() {
                var options, name, src, copy, copyIsArray, clone,
                    target = arguments[0],
                    i = 1,
                    length = arguments.length,
                    deep = false;

                // Handle a deep copy situation
                if (typeof target === 'boolean') {
                    deep = target;
                    target = arguments[1] || {};
                    // skip the boolean and the target
                    i = 2;
                } else if ((typeof target !== 'object' && typeof target !== 'function') || target == null) {
                    target = {};
                }

                for (; i < length; ++i) {
                    options = arguments[i];
                    // Only deal with non-null/undefined values
                    if (options != null) {
                        // Extend the base object
                        for (name in options) {
                            src = target[name];
                            copy = options[name];

                            // Prevent never-ending loop
                            if (target !== copy) {
                                // Recurse if we're merging plain objects or arrays
                                if (deep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) {
                                    if (copyIsArray) {
                                        copyIsArray = false;
                                        clone = src && isArray(src) ? src : [];
                                    } else {
                                        clone = src && isPlainObject(src) ? src : {};
                                    }

                                    // Never move original objects, clone them
                                    target[name] = extend(deep, clone, copy);

                                    // Don't bring in undefined values
                                } else if (typeof copy !== 'undefined') {
                                    target[name] = copy;
                                }
                            }
                        }
                    }
                }

                // Return the modified object
                return target;
            };


        }, {}],
        4: [function (require, module, exports) {
            'use strict';

            Object.defineProperty(exports, '__esModule', {
                value: true
            });

            var _createClass = (function () {
                function defineProperties(target, props) {
                    for (var i = 0; i < props.length; i++) {
                        var descriptor = props[i];
                        descriptor.enumerable = descriptor.enumerable || false;
                        descriptor.configurable = true;
                        if ('value' in descriptor) descriptor.writable = true;
                        Object.defineProperty(target, descriptor.key, descriptor);
                    }
                }

                return function (Constructor, protoProps, staticProps) {
                    if (protoProps) defineProperties(Constructor.prototype, protoProps);
                    if (staticProps) defineProperties(Constructor, staticProps);
                    return Constructor;
                };
            })();

            function _interopRequireDefault(obj) {
                return obj && obj.__esModule ? obj : {'default': obj};
            }

            function _classCallCheck(instance, Constructor) {
                if (!(instance instanceof Constructor)) {
                    throw new TypeError('Cannot call a class as a function');
                }
            }

            var _arrify = require('arrify');

            var _arrify2 = _interopRequireDefault(_arrify);

            var _extend = require('extend');

            var _extend2 = _interopRequireDefault(_extend);

            var _elementsNode = require('./elements/node');

            var _elementsNode2 = _interopRequireDefault(_elementsNode);

            var _elementsEdge = require('./elements/edge');

            var _elementsEdge2 = _interopRequireDefault(_elementsEdge);

            var _Graph = require('./Graph');

            var _Graph2 = _interopRequireDefault(_Graph);

            var _selectorGreulerDefaultTransition = require('./selector/GreulerDefaultTransition');

            var _selectorGreulerDefaultTransition2 = _interopRequireDefault(_selectorGreulerDefaultTransition);

            var d3 = window.d3;
            var cola = window.cola;

            var Draw = (function () {
                function Draw(id, options) {
                    _classCallCheck(this, Draw);

                    var self = this;
                    this.events = d3.dispatch('layout', 'firstLayoutEnd');

                    this.markerId = 'marker-' + id;

                    this.defaultOptions(options);

                    // graph handles the interactions with the drawer
                    this.createGraph();

                    // selector animates the nodes/edges
                    this.selector = new _selectorGreulerDefaultTransition2['default'](this);

                    // sub-elements that draw stuff
                    this.nodeDrawer = (0, _elementsNode2['default'])().owner(this);
                    this.edgeDrawer = (0, _elementsEdge2['default'])().owner(this);

                    // cola
                    this.layout = cola.d3adaptor();

                    this.layout.on('tick', function () {
                        self.tick();
                    });

                    var firstEnd = true;
                    this.layout.on('end', function () {
                        if (firstEnd) {
                            self.events.firstLayoutEnd();
                            firstEnd = false;
                        }
                    });
                }

                _createClass(Draw, [{
                    key: 'createGraph',
                    value: function createGraph() {
                        var data = this.options.data;
                        var nodes = data.nodes;
                        var links = data.links;

                        // empty and re-add
                        data.nodes = [];
                        data.links = [];

                        this.graph = new _Graph2['default'](this, data);
                        nodes.forEach(function (node) {
                            this.graph.addNode(node);
                        }, this);
                        links.forEach(function (edge) {
                            this.graph.addEdge(edge);
                        }, this);
                    }

                    /**
                     *
                     * @param {Object} options
                     *
                     * options
                     *   - target {string} selector to the element to hold the graph
                     *   - width {number}
                     *   - height {number}
                     *   - labels=true {boolean} False to hide the vertex labels
                     *   - directed=false {boolean} True to give an orientation to the edges
                     *   have an edge
                     *   - data {Object}
                     *     - linkDistance=90 {number} Forced min distance between vertices that
                     *     - constraints {Array[Objects]}
                     *     - groups {Array[Objects]}
                     *     - nodes {Array[Objects]}
                     *       - r=10 {number} node radius
                     *     - links {Array[Objects]}
                     *       - directed=false {boolean} true to give an orientation to this edge
                     *       - weight="" {string} Label of the edge (can be the weight)
                     *
                     */
                }, {
                    key: 'defaultOptions',
                    value: function defaultOptions(options) {
                        // graph defaults
                        options = this.options = (0, _extend2['default'])({
                            width: 700,
                            height: 300,
                            animationTime: 1000,
                            labels: true,
                            directed: false
                        }, options);

                        this.options.data = (0, _extend2['default'])({
                            nodes: [],
                            links: [],
                            groups: [],
                            constraints: [],
                            avoidOverlaps: true,
                            size: [options.width, options.height],
                            linkDistance: function linkDistance(d) {
                                return d.linkDistance || 80;
                            }
                        }, this.options.data);
                    }
                }, {
                    key: 'initLayout',
                    value: function initLayout(updateOptions) {
                        var self = this;

                        if (updateOptions.skipLayout) {
                            return;
                        }

                        var receivesArray = {
                            nodes: true,
                            links: true,
                            groups: true,
                            constraints: true,
                            distanceMatrix: true,
                            size: true
                        };

                        Object.keys(self.options.data).forEach(function (k) {
                            var v = self.options.data[k];
                            if (receivesArray[k]) {
                                self.layout[k]((0, _arrify2['default'])(v));
                            } else {
                                self.layout[k].apply(self.layout, (0, _arrify2['default'])(v));
                            }
                        }, this);

                        this.layout.start.apply(this.layout, updateOptions.iterations);
                    }
                }, {
                    key: 'tick',
                    value: function tick() {
                        this.edgeGroup.call(this.edgeDrawer);
                        this.nodeGroup.call(this.nodeDrawer);
                    }
                }, {
                    key: 'update',
                    value: function update(updateOptions) {
                        updateOptions = (0, _extend2['default'])(true, {
                            skipLayout: false,
                            iterations: []
                        }, updateOptions);

                        this.initLayout(updateOptions);
                        this.build(updateOptions);

                        // update nodes/edges if layout.tick wasn't run
                        if (updateOptions.skipLayout) {
                            this.tick();
                        }

                        return this;
                    }
                }, {
                    key: 'build',
                    value: function build() {
                        this.root = d3.select(this.options.target).selectAll('svg.greuler').data([this.options]);

                        // enter
                        this.root.enter = this.root.enter().append('svg').attr('class', 'greuler');

                        // marker def
                        this.root.enter.append('svg:defs').append('svg:marker').attr('id', this.markerId).attr('viewBox', '0 -5 10 10').attr('refX', 9).attr('markerWidth', 10).attr('markerHeight', 10).attr('markerUnits', 'userSpaceOnUse').attr('orient', 'auto').append('svg:path').attr('d', 'M0,-4L10,0L0,4L2,0').attr('stroke-width', '0px').attr('fill-opacity', 1).attr('fill', '#777');

                        // update
                        this.root.attr('width', this.options.width).attr('height', this.options.height);

                        // wrapper for the edges
                        this.edgeGroup = this.root.selectAll('g.edges').data(function (d) {
                            return [d.data];
                        });
                        this.edgeGroup.enter().append('g').attr('class', 'edges');

                        // wrapper for the nodes
                        this.nodeGroup = this.root.selectAll('g.nodes').data(function (d) {
                            return [d.data];
                        });
                        this.nodeGroup.enter().append('g').attr('class', 'nodes');
                    }
                }]);

                return Draw;
            })();

            exports['default'] = Draw;
            module.exports = exports['default'];

        }, {
            "./Graph": 5,
            "./elements/edge": 8,
            "./elements/node": 9,
            "./selector/GreulerDefaultTransition": 16,
            "arrify": 1,
            "extend": 3
        }],
        5: [function (require, module, exports) {
            'use strict';

            Object.defineProperty(exports, '__esModule', {
                value: true
            });

            var _createClass = (function () {
                function defineProperties(target, props) {
                    for (var i = 0; i < props.length; i++) {
                        var descriptor = props[i];
                        descriptor.enumerable = descriptor.enumerable || false;
                        descriptor.configurable = true;
                        if ('value' in descriptor) descriptor.writable = true;
                        Object.defineProperty(target, descriptor.key, descriptor);
                    }
                }

                return function (Constructor, protoProps, staticProps) {
                    if (protoProps) defineProperties(Constructor.prototype, protoProps);
                    if (staticProps) defineProperties(Constructor, staticProps);
                    return Constructor;
                };
            })();

            function _interopRequireDefault(obj) {
                return obj && obj.__esModule ? obj : {'default': obj};
            }

            function _classCallCheck(instance, Constructor) {
                if (!(instance instanceof Constructor)) {
                    throw new TypeError('Cannot call a class as a function');
                }
            }

            var _extend = require('extend');

            var _extend2 = _interopRequireDefault(_extend);

            var _utils = require('./utils');

            var _utils2 = _interopRequireDefault(_utils);

            var _const = require('./const');

            var NODE_DEFAULT_OPTIONS = {
                r: 11,
                fill: '#525252'
            };

            var EDGE_DEFAULT_OPTIONS = {
                stroke: _const.colors.LIGHT_GRAY
            };

            function includes(arr, id) {
                for (var i = 0; i < arr.length; i += 1) {
                    if (arr[i].id === id) {
                        return true;
                    }
                }
            }

            var Graph = (function () {
                function Graph(owner, data) {
                    _classCallCheck(this, Graph);

                    this.owner = owner;
                    this.nodes = data.nodes;
                    this.edges = data.links;
                }

                /**
                 * Adds a node to the graph, each of the arguments must
                 * be an object with the following required properties
                 *
                 * - id {Number|string}
                 *
                 * Optional properties
                 *
                 * - x {number} The x coordinate of this node in the graph (only if fixed = true)
                 * - y {number} The y coordinate of this node in the graph (only if fixed = true)
                 * - fixed {boolean} `true` to make this node not to participate in the layout process
                 * - fill {string} The fill of the circle that represents the node
                 * - r {number} The radius of the circle that represents the node
                 * - label {string} The text inside the node (if it's not present it's equal to the `id`)
                 * - topRightLabel {string] the text shown on the top right side of the node, useful
   * to represent additional annotations
   *
   * NOTE: this function receives any number of arguments
   */

                _createClass(Graph, [{
                    key: 'addNode',
                    value: function addNode() {
                        for (var i = 0; i < arguments.length; i += 1) {
                            var config = arguments[i];
                            if (!config.hasOwnProperty('id')) {
                                throw Error('the object must have the property `id`');
                            }
                            if (this.getNode(config)) {
                                throw Error('node already in store');
                            }
                            this.nodes.push(Graph.appendNodeDefaults.call(this.owner, config));
                        }
                    }

                    /**
                     * Gets a node by id
                     *
                     * @param {Object} node
                     * @param {number|string} node.id The id of the node
                     * @returns {Object|undefined}
                     */
                }, {
                    key: 'getNode',
                    value: function getNode(node) {
                        return this.getNodesByFn(function (v) {
                            return v.id === node.id;
                        })[0];
                    }

                }, {
                    key: 'hasNode',
                    value: function getNode(node) {
                        return this.getNodesByFn(function (v) {
                            return v.id === node.id;
                        }).length > 0;
                    }


                    /**
                     * Returns all the nodes that satisfy the parameter `fn`,
                     * alias for `this.nodes.filter(fn)`
                     *
                     * @param {Function} fn
                     * @returns {Object[]}
                     */
                }, {
                    key: 'getNodesByFn',
                    value: function getNodesByFn(fn) {
                        return this.nodes.filter(fn);
                    }

                    /**
                     * Gets all the adjacent nodes of the node identified by `id`
                     *
                     * @param {Object} node
                     * @param {number|string} node.id The id of the node
                     * @returns {Object[]}
                     */
                }, {
                    key: 'getAdjacentNodes',
                    value: function getAdjacentNodes(node) {
                        var adjacentNodes = [];
                        var taken = {};
                        var next;
                        for (var i = 0; i < this.edges.length; i += 1) {
                            var edge = this.edges[i];
                            next = null;
                            if (edge.source.id === node.id) {
                                next = edge.target;
                            } else if (edge.target.id === node.id) {
                                next = edge.source;
                            }

                            if (next && !taken[next.id]) {
                                taken[next.id] = true;
                                adjacentNodes.push(next);
                            }
                        }

                        return adjacentNodes;
                    }

                    /**
                     * Gets all the successor nodes of the node identified by `id`
                     *
                     * @param {Object} node
                     * @param {number|string} node.id The id of the node
                     * @returns {Object[]}
                     */
                }, {
                    key: 'getSuccessorNodes',
                    value: function getSuccessorNodes(node) {
                        var successor = [];
                        var taken = {};
                        var next;
                        for (var i = 0; i < this.edges.length; i += 1) {
                            var edge = this.edges[i];
                            next = null;
                            if (edge.source.id === node.id) {
                                next = edge.target;
                            }
                            if (next && !taken[next.id]) {
                                taken[next.id] = true;
                                successor.push(next);
                            }
                        }

                        return successor;
                    }

                    /**
                     * Gets all the predecessor nodes of the node identified by `id`
                     *
                     * @param {Object} node
                     * @param {number|string} node.id The id of the node
                     * @returns {Object[]}
                     */
                }, {
                    key: 'getPredecessorNodes',
                    value: function getPredecessorNodes(node) {
                        var predecessor = [];
                        var taken = {};
                        var next;
                        for (var i = 0; i < this.edges.length; i += 1) {
                            var edge = this.edges[i];
                            next = null;
                            if (edge.target.id === node.id) {
                                next = edge.source;
                            }
                            if (next && !taken[next.id]) {
                                taken[next.id] = true;
                                predecessor.push(next);
                            }
                        }

                        return predecessor;
                    }

                    /**
                     * Removes a node identified by `id`
                     *
                     * @param {Object} node
                     * @param {number|string} node.id The id of the node
                     */
                }, {
                    key: 'removeNode',
                    value: function removeNode(node) {
                        this.removeNodesByFn(function (v) {
                            return v.id === node.id;
                        });
                    }

                    /**
                     * Removes all the nodes stored in `nodes`,
                     * each object must have the property `id`
                     *
                     * @param {Object[]} nodes
                     */
                }, {
                    key: 'removeNodes',
                    value: function removeNodes(nodes) {
                        // TODO: improve n^2 removal
                        this.removeNodesByFn(function (v) {
                            return includes(nodes, v.id);
                        });
                    }

                    /**
                     * Removes all the nodes that satisfy the predicate
                     * `fn`
                     *
                     * @param {Function} fn
                     */
                }, {
                    key: 'removeNodesByFn',
                    value: function removeNodesByFn(fn) {
                        var i;
                        for (i = 0; i < this.nodes.length; i += 1) {
                            if (fn(this.nodes[i], i)) {
                                // remove nodes
                                var node = this.nodes.splice(i, 1);
                                // remove incident edges
                                this.removeEdges(this.getIncidentEdges(node[0]));
                                i -= 1;
                            }
                        }
                    }

                    /**
                     * Adds an edge to the graph, each of the arguments must
                     * be an object with the following properties
                     *
                     * Required properties
                     *
                     * - source {number|Object} The id of the source node or the source node itself
                     * - target {number|Object} The id of the target node or the target node itself
                     *
                     * Optional properties
                     *
                     * - id {string|Object} If an id is not provided an auto generated string will be assigned
                     * to this edge
                     * - stroke {string} The stroke of the path that represents the edge
                     * - weight {string} The weight of the edge
                     * - directed {boolean} If set to true an additional arrow is added at the end of the edge
                     *
                     * NOTE: this function receives any number of arguments
                     */
                }, {
                    key: 'addEdge',
                    value: function addEdge() {
                        for (var i = 0; i < arguments.length; i += 1) {
                            var config = arguments[i];

                            if (!config.hasOwnProperty('source') || !config.hasOwnProperty('target')) {
                                throw Error('the edge must have the properties `source` and `target`');
                            }
                            var source = config.source;
                            var target = config.target;

                            if (typeof source !== 'object') {
                                source = this.getNode({id: config.source});
                            }

                            if (typeof target !== 'object') {
                                target = this.getNode({id: config.target});
                            }

                            if (!source || !target) {
                                throw Error('new edge does not join existing vertices');
                            }
                            config.source = source;
                            config.target = target;
                            this.edges.push(Graph.appendEdgeDefaults.call(this.owner, config));
                        }
                    }

                    /**
                     * Gets an edge by `id`
                     *
                     * @param {Object} edge
                     * @param {number|string} edge.id The id of the edge
                     * @returns {Object}
                     */
                }, {
                    key: 'getEdge',
                    value: function getEdge(edge) {
                        return this.getEdgesByFn(function (e) {
                            return e.id === edge.id;
                        })[0];
                    }
                }, {
                    key: 'hasEdge',
                    value: function getEdge(edge) {
                        return this.getEdgesByFn(function (e) {
                            return e.id === edge.id;
                        }).length > 0;
                    }

                    /**
                     * Gets all the directed edges from the node whose id is
                     * `options.source` and to the node whose id is `options.target`
                     *
                     * @param {Object} options
                     * @param {number|string} options.source The id of the source node
                     * @param {number|string} options.target The id of the target node
                     * @returns {Object[]}
                     */
                }, {
                    key: 'getEdgesBetween',
                    value: function getEdgesBetween(options) {
                        return this.getEdgesByFn(function (e) {
                            return e.source.id === options.source && e.target.id === options.target;
                        });
                    }

                    /**
                     * Gets all the edges from `options.source` to `options.target`
                     * or `options.target` to `options.source`
                     *
                     * @param {Object} options
                     * @param {number|string} options.source The id of the source node
                     * @param {number|string} options.target The id of the target node
                     * @returns {Object[]}
                     */
                }, {
                    key: 'getAllEdgesBetween',
                    value: function getAllEdgesBetween(options) {
                        return this.getEdgesByFn(function (e) {
                            return e.source.id === options.source && e.target.id === options.target || e.source.id === options.target && e.target.id === options.source;
                        });
                    }

                    /**
                     * Removes an edge identified by id
                     *
                     * @param {Object} edge
                     * @param {number|string} edge.id The id of the edge
                     */
                }, {
                    key: 'removeEdge',
                    value: function removeEdge(edge) {
                        this.removeEdgesByFn(function (e) {
                            return e.id === edge.id;
                        });
                    }

                    /**
                     * Removes all the edges stored in `edges`,
                     * each object must have the property `id`
                     *
                     * @param {Object[]} edges
                     */
                }, {
                    key: 'removeEdges',
                    value: function removeEdges(edges) {
                        // TODO: improve n^2 removal
                        this.removeEdgesByFn(function (e) {
                            return includes(edges, e.id);
                        });
                    }

                    /**
                     * Removes all the edges that return true for the predicate
                     * `fn`
                     *
                     * @param {function} fn
                     */
                }, {
                    key: 'removeEdgesByFn',
                    value: function removeEdgesByFn(fn) {
                        var i;
                        for (i = 0; i < this.edges.length; i += 1) {
                            if (fn(this.edges[i], i)) {
                                this.edges.splice(i, 1);
                                i -= 1;
                            }
                        }
                    }

                    /**
                     * Gets all the edges that return true for the predicate `fn`
                     *
                     * @param {Function} fn
                     * @returns {Object[]}
                     */
                }, {
                    key: 'getEdgesByFn',
                    value: function getEdgesByFn(fn) {
                        return this.edges.filter(fn);
                    }

                    /**
                     * Gets all the outgoing edges of the node `id`
                     *
                     * @param {Object} node
                     * @param {number|string} node.id The id of the node
                     * @returns {Object[]}
                     */
                }, {
                    key: 'getOutgoingEdges',
                    value: function getOutgoingEdges(node) {
                        return this.getEdgesByFn(function (e) {
                            return e.source.id === node.id;
                        });
                    }

                    /**
                     * Gets all the incoming edges of the node `id`
                     *
                     * @param {Object} node
                     * @param {number|string} node.id The id of the node
                     * @returns {Object[]}
                     */
                }, {
                    key: 'getIncomingEdges',
                    value: function getIncomingEdges(node) {
                        return this.getEdgesByFn(function (e) {
                            return e.target.id === node.id;
                        });
                    }

                    /**
                     * Gets all the incident edges of the node `id`
                     *
                     * @param {Object} node
                     * @param {number|string} node.id The id of the node
                     * @returns {Object[]}
                     */
                }, {
                    key: 'getIncidentEdges',
                    value: function getIncidentEdges(node) {
                        return this.getOutgoingEdges(node).concat(this.getIncomingEdges(node));
                    }

                    /**
                     * Facade to add nodes/edges
                     *
                     * NOTE: the function receives any number of parameters
                     */
                }, {
                    key: 'add',
                    value: function add() {
                        for (var i = 0; i < arguments.length; i += 1) {
                            var el = arguments[i];
                            // assume that edges have a source/target parameter
                            if (el.hasOwnProperty('source') && el.hasOwnProperty('target')) {
                                this.addEdge(el);
                            } else {
                                this.addNode(el);
                            }
                        }
                    }
                }], [{
                    key: 'appendNodeDefaults',
                    value: function appendNodeDefaults(v) {
                        if (!v.hasOwnProperty('id')) {
                            v.id = _utils2['default'].id();
                        }

                        v = (0, _extend2['default'])({},
                            // predefined defaults
                            NODE_DEFAULT_OPTIONS,
                            // instance defaults
                            this.options.nodeDefaults,
                            // node
                            v);

                        if (!v.hasOwnProperty('width')) {
                            v.width = 2 * v.r;
                        }
                        if (!v.hasOwnProperty('height')) {
                            v.height = 2 * v.r;
                        }
                        return v;
                    }
                }, {
                    key: 'appendEdgeDefaults',
                    value: function appendEdgeDefaults(e) {
                        if (!e.hasOwnProperty('id')) {
                            e.id = _utils2['default'].id();
                        }
                        e = (0, _extend2['default'])({},
                            // predefined defaults
                            EDGE_DEFAULT_OPTIONS,
                            // instance defaults
                            this.options.edgeDefaults,
                            // edge
                            e);
                        return e;
                    }

                    /**
                     * Creates a random graph with the following defaults options overridden by `options`:
                     *
                     * - options.order=10 {number} The number of nodes in the graph
                     * - options.size=15 {number} The number of edges in the graph
                     * - options.connected=false {boolean} True to make the graph connected,
                     * it's guaranteed to have at least `options.order - 1` edges
                     * - options.multiGraph=false {boolean} True to allow the creation of parallel edges
                     * - options.pseudoGraph=false {boolean} True to allow the creation of loop edges
                     *
                     * @param {Object} options
                     * @returns {{nodes: Array, links: Array}}
                     */
                }, {
                    key: 'random',
                    value: function random(options) {
                        options = (0, _extend2['default'])({
                            order: 10,
                            size: 15,
                            connected: false,
                            multiGraph: false,
                            pseudoGraph: false
                        }, options);

                        var i, u, v;
                        var nodes = [];
                        var adjacencyList = [];
                        for (i = 0; i < options.order; i += 1) {
                            adjacencyList[i] = [];
                            nodes.push({id: i});
                        }

                        function add(u, v) {
                            adjacencyList[u][v] = adjacencyList[v][u] = true;
                        }

                        var edges = [];
                        i = 0;

                        if (options.connected) {
                            for (i = 1; i < options.order; i += 1) {
                                v = Math.floor(Math.random() * i);
                                add(i, v);
                                edges.push({
                                    source: i,
                                    target: v
                                });
                            }
                            i -= 1;
                        }

                        for (; i < options.size; i += 1) {
                            u = Math.floor(Math.random() * options.order);
                            v = Math.floor(Math.random() * options.order);

                            if (u === v && !options.pseudoGraph) {
                                i -= 1;
                            } else if (adjacencyList[u][v] && !options.multiGraph) {
                                i -= 1;
                            } else {
                                add(u, v);
                                edges.push({
                                    source: u,
                                    target: v
                                });
                            }
                        }

                        return {
                            nodes: nodes,
                            links: edges
                        };
                    }
                }]);

                return Graph;
            })();

            exports['default'] = Graph;
            module.exports = exports['default'];

        }, {"./const": 7, "./utils": 17, "extend": 3}],
        6: [function (require, module, exports) {
            'use strict';

            Object.defineProperty(exports, '__esModule', {
                value: true
            });

            var _createClass = (function () {
                function defineProperties(target, props) {
                    for (var i = 0; i < props.length; i++) {
                        var descriptor = props[i];
                        descriptor.enumerable = descriptor.enumerable || false;
                        descriptor.configurable = true;
                        if ('value' in descriptor) descriptor.writable = true;
                        Object.defineProperty(target, descriptor.key, descriptor);
                    }
                }

                return function (Constructor, protoProps, staticProps) {
                    if (protoProps) defineProperties(Constructor.prototype, protoProps);
                    if (staticProps) defineProperties(Constructor, staticProps);
                    return Constructor;
                };
            })();

            function _classCallCheck(instance, Constructor) {
                if (!(instance instanceof Constructor)) {
                    throw new TypeError('Cannot call a class as a function');
                }
            }

            var Vector = (function () {
                function Vector(x, y) {
                    _classCallCheck(this, Vector);

                    this.x = x;
                    this.y = y;
                }

                // unary

                _createClass(Vector, null, [{
                    key: 'neg',
                    value: function neg(a) {
                        return new Vector(-a.x, -a.y);
                    }
                }, {
                    key: 'len',
                    value: function len(a) {
                        return Math.sqrt(Vector.lenSq(a));
                    }
                }, {
                    key: 'lenSq',
                    value: function lenSq(a) {
                        return a.x * a.x + a.y * a.y;
                    }
                }, {
                    key: 'unit',
                    value: function unit(a) {
                        if (a.x === 0 && a.y === 0) {
                            throw Error('the length of the vector is 0');
                        }
                        var length = this.len(a);
                        return new Vector(a.x / length, a.y / length);
                    }
                }, {
                    key: 'orthogonal',
                    value: function orthogonal(a) {
                        return new Vector(-a.y, a.x);
                    }
                }, {
                    key: 'angleDeg',
                    value: function angleDeg(a) {
                        return Math.atan2(a.y, a.x) * 180 / Math.PI;
                    }

                    // binary

                }, {
                    key: 'add',
                    value: function add(a, b) {
                        return new Vector(a.x + b.x, a.y + b.y);
                    }
                }, {
                    key: 'sub',
                    value: function sub(a, b) {
                        return new Vector(a.x - b.x, a.y - b.y);
                    }
                }, {
                    key: 'dot',
                    value: function dot(a, b) {
                        return a.x * b.x + a.y * b.y;
                    }
                }, {
                    key: 'scale',
                    value: function scale(a, n) {
                        return new Vector(a.x * n, a.y * n);
                    }
                }, {
                    key: 'mid',
                    value: function mid(a, b) {
                        return Vector.scale(Vector.add(a, b), 0.5);
                    }
                }, {
                    key: 'angleBetween',
                    value: function angleBetween(a, b) {
                        return Math.acos(Vector.dot(a, b) / Vector.len(a) - Vector.len(b));
                    }
                }, {
                    key: 'rotate',
                    value: function rotate(a, angle) {
                        var cosA = Math.cos(angle);
                        var sinA = Math.sin(angle);
                        var nx = a.x * cosA - a.y * sinA;
                        var ny = a.x * sinA + a.y * cosA;
                        return new Vector(nx, ny);
                    }
                }]);

                return Vector;
            })();

            exports['default'] = Vector;
            module.exports = exports['default'];

        }, {}],
        7: [function (require, module, exports) {
            'use strict';

            Object.defineProperty(exports, '__esModule', {
                value: true
            });
            var d3 = window.d3;
            var color = d3.scale.category20();
            var colors = {};
            var colorLiterals = ['BLUE', 'ORANGE', 'GREEN', 'RED', 'PURPLE', 'BROWN', 'PINK', 'GRAY', 'YELLOW', 'CYAN'];
            colorLiterals.forEach(function (c, i) {
                colors[c] = color.range()[2 * i];
                colors['LIGHT_' + c] = color.range()[2 * i + 1];
            });

            colors.randomFromPalette = function () {
                return color.range()[Math.floor(Math.random() * 20)];
            };

            exports.colors = colors;

        }, {}],
        8: [function (require, module, exports) {
            'use strict';

            Object.defineProperty(exports, '__esModule', {
                value: true
            });

            function _interopRequireDefault(obj) {
                return obj && obj.__esModule ? obj : {'default': obj};
            }

            var _extend = require('extend');

            var _extend2 = _interopRequireDefault(_extend);

            var _Vector = require('../Vector');

            var _Vector2 = _interopRequireDefault(_Vector);

            var _utils = require('../utils');

            var _utils2 = _interopRequireDefault(_utils);

            var d3 = window.d3;

            exports['default'] = function () {
                var owner;

                function moveTowardsPoint(point, middle) {
                    var margin = point.r;
                    var unit = _Vector2['default'].unit(_Vector2['default'].sub(middle, point));
                    return _Vector2['default'].add(point, _Vector2['default'].scale(unit, margin));
                }

                /**
                 * Computes the inner points of a loop edge
                 *
                 * - analyzes each adjacent vertex
                 *  - for each each edge u-v move the opposite way e.g. v->u
                 *  - the sum of unit vectors will give roughly a good approximation
                 *
                 * @param {Object} u Vertex
                 * @param {number} marginBetweenEdges Defined in `createPath`
                 * @param {number} count The number of u-u edges found yet
                 * @returns {{path: *[], dir: *}}
                 */
                function selfLoop(u, marginBetweenEdges, count) {
                    var adjacent = owner.graph.getAdjacentNodes(u);
                    var dir = new _Vector2['default'](0, 0);
                    for (var i = 0; i < adjacent.length; i += 1) {
                        var v = adjacent[i];
                        if (u.id !== v.id) {
                            dir = _Vector2['default'].unit(_Vector2['default'].add(dir, _Vector2['default'].unit(_Vector2['default'].sub(u, v))));
                        }
                    }

                    function toRad(a) {
                        return a * Math.PI / 180;
                    }

                    // no adjacent vertices
                    if (dir.x === 0 && dir.y === 0) {
                        dir = _Vector2['default'].unit(new _Vector2['default'](0, -1));
                    }

                    var ort = _Vector2['default'].orthogonal(dir);

                    // moving u towards `dir` `u.r` units
                    var uBorderOrigin = _Vector2['default'].scale(dir, u.r + 4);
                    // var uBorderOriginTwice = Vector.scale(dir, u.r * 2)
                    // uD is now in the edge of the circle, making a little arc in the circle

                    // endpoints of the edge will have a separation of 25 deg, 50 deg, 75 deg, ...
                    var separation = toRad(25);
                    var angle = separation + (count - 1) * separation;

                    // the point to the left of u + uBorder
                    var uBorderLeft = _Vector2['default'].add(u, _Vector2['default'].rotate(uBorderOrigin, angle));
                    // the point to the right of u + uBorder
                    var uBorderRight = _Vector2['default'].add(u, _Vector2['default'].rotate(uBorderOrigin, -angle));

                    // some length away from the node computed by doing random samples
                    var length = marginBetweenEdges * 0.6 * (count + 1);

                    /*
                     * Form the shape of a weird rhombus
                     *
                     *
                     *            up
                     *           /  \
                     *          /    \
                     *         /      \
                     *        /        \
                     *     left       right
                     *       \         /
                     *     border   border
                     *
                     */
                    var up = _Vector2['default'].add(u, _Vector2['default'].scale(dir, u.r + length));

                    var midLeft = _Vector2['default'].add(uBorderLeft, _Vector2['default'].scale(dir, length * 0.5));
                    var midRight = _Vector2['default'].add(uBorderRight, _Vector2['default'].scale(dir, length * 0.5));

                    var left = _Vector2['default'].add(midLeft, _Vector2['default'].scale(ort, length / 4));
                    var right = _Vector2['default'].add(midRight, _Vector2['default'].scale(ort, -length / 4));

                    return {
                        path: [uBorderLeft, left, up, right, uBorderRight],
                        dir: ort
                    };
                }

                /**
                 * Creates the points of the <path> that represent an edge
                 *
                 * @param {Object} d Edge
                 * @param {Object} meta Holds the edge count between vertices,
                 * unit vectors and other metadata
                 * @param {number} marginBetweenEdges Used in both normal and
                 * loop edges sets the separation between edges from the mid
                 * point of the vertices they join
                 */
                function createPath(d, meta, marginBetweenEdges) {
                    var u, v;
                    var uBorder, vBorder;
                    var current;

                    u = d.source;
                    v = d.target;
                    if (u.id > v.id) {
                        var _ref = [v, u];
                        u = _ref[0];
                        v = _ref[1];
                    }
                    meta[u.id] = meta[u.id] || {};

                    // the mid point is computed from the borders of both nodes
                    // the mid point is used to determine the position of the label
                    uBorder = u;
                    vBorder = v;
                    if (u.id !== v.id) {
                        uBorder = moveTowardsPoint(u, v);
                        vBorder = moveTowardsPoint(v, u);
                    }

                    current = meta[u.id][v.id] = meta[u.id][v.id] || {
                        count: 1,
                        mid: _Vector2['default'].mid(uBorder, vBorder),
                        direction: -1
                    };

                    var innerJoints = [];
                    if (u.id === v.id) {
                        // apply the following for self-loop edges
                        var loop = selfLoop(u, marginBetweenEdges, current.count);
                        innerJoints = loop.path;
                        d.unit = loop.dir;
                    } else {
                        var unit = _Vector2['default'].unit(_Vector2['default'].sub(v, u));
                        (0, _extend2['default'])(current, {
                            unit: unit,
                            unitOrthogonal: _Vector2['default'].orthogonal(unit)
                        });
                        innerJoints.push(_Vector2['default'].add(current.mid, _Vector2['default'].scale(current.unitOrthogonal, Math.floor(current.count / 2) * marginBetweenEdges * current.direction)));
                        d.unit = current.unit;
                    }

                    current.count += 1;
                    current.direction *= -1;

                    // problem: the edge starts/ends in the center of some node
                    //
                    // real solution: render the path normally then compute the position of a point
                    // with `path.getPointAtLength(t * l)` where `l` is the length of the path and
                    // `t` an interpolated place = radius of each node
                    //
                    // simple trick: shorten the length of the edge by moving the start/end points
                    // of the edges toward each other
                    var source = moveTowardsPoint(d.source, innerJoints[0]);
                    var target = moveTowardsPoint(d.target, innerJoints[innerJoints.length - 1]);

                    d.path = [source].concat(innerJoints).concat([target]);
                }

                var line = d3.svg.line().x(function (d) {
                    return d.x;
                }).y(function (d) {
                    return d.y;
                }).tension(1.5).interpolate('bundle');

                // .interpolate('linear')

                function inner(selection) {
                    // edges
                    var links = selection.selectAll('g.edge').data(function (d) {
                        return d.links;
                    }, function (d) {
                        return d.id;
                    });
                    links.enter().append('g').attr('class', 'edge').attr('opacity', 0).attr('id', function (d) {
                        return _utils2['default'].ns(d.id);
                    }).transition('enter').attr('opacity', 1);

                    // update
                    links.each(function (d) {
                        var self = d3.select(this);
                        var cls = {
                            directed: d.directed || owner.options.directed
                        };
                        cls['source-' + d.source.id] = true;
                        cls['target-' + d.target.id] = true;
                        self.classed(cls);
                    });

                    var meta = {};
                    links.each(function (d) {
                        createPath(d, meta, 17);
                    });

                    // path enter
                    var paths = links.selectAll('path').data(function (d) {
                        // 1. real path
                        // 2. stroke-dasharray helper
                        return [d, d];
                    });
                    paths.enter().append('path').attr('stroke', function (d) {
                        return d.stroke;
                    }).attr('fill', 'transparent').attr('stroke-width', function (d) {
                        return d.lineWidth;
                    }).each(function (d, i) {
                        var el = d3.select(this);
                        el.attr('opacity', !i ? 1 : 0);
                        if (i === 0) {
                            el.classed('base', true);
                        }
                        if (i === 1) {
                            el.attr('stroke-width', 5);
                            el.classed('traversal', true);
                        }
                    });
                    // .attr('d', function () {
                    //  var parent = d3.select(this.parentNode).datum()
                    //  return line([parent.source])
                    // })

                    // path update
                    _utils2['default'].conditionalTransition(paths, !owner.nodeDragging).attr('d', function (d) {
                        return line(d.path);
                    });

                    paths.each(function (d, i) {
                        var path = d3.select(this);
                        var parent = d3.select(this.parentNode);
                        if (i === 0) {
                            path.attr('marker-end', parent.classed('directed') ? 'url(#' + owner.markerId + ')' : null);
                        }
                    });

                    function weightPosition(selection) {
                        selection.attr('transform', function (d) {
                            var angle = _Vector2['default'].angleDeg(d.unit);
                            var v = d.path[Math.floor(d.path.length / 2)];
                            return _utils2['default'].transform({
                                translate: v,
                                rotate: angle,
                                scale: (angle > 90 || angle < -90) ? -1.0 : 1.0
                            });
                        });
                    }

                    var weights = links.selectAll('text').data(function (d) {
                        return [d];
                    });

                    function newLineParser(s, fontSize) {
                        var newS = '';
                        var lines = s.split('\n');
                        var dy = -(lines.length - 1) * 1.2 * fontSize - 3;
                        for (var i = 0; i < lines.length; i++) {
                            newS += "<tspan x='0px' y='" + (1.2 * fontSize * i) + "px' dy='" + dy + "px'>";
                            newS += lines[i];
                            newS += "</tspan>";
                        }
                        return newS;
                    }

                    // weight enter
                    weights.enter().append('text').attr('font-family', 'Oswald').attr('dominant-baseline', 'alphabetic').attr('text-anchor', 'middle').attr('pointer-events', 'none').attr('paint-order', 'stroke').attr('stroke-linecap', 'round').attr('stroke-linejoin', 'round').attr('vector-effect', 'non-scaling-stroke').call(weightPosition);
                    links.selectAll('text').attr('font-size', function (d) {
                        return String(d.weightStyle).split(',')[0] + 'px'
                    });
                    links.selectAll('text').attr('fill', function (d) {
                        return String(d.weightStyle).split(',')[1]
                    });
                    links.selectAll('text').attr('stroke', function (d) {
                        return String(d.weightStyle).split(',')[2]
                    });
                    links.selectAll('text').attr('stroke-width', function (d) {
                        return String(Math.min(Math.floor((parseFloat(String(d.weightStyle).split(',')[0]) / 14.0) * 6.0), 6.0)) + 'px'
                    });
                    links.selectAll('text').html(function (d) {
                        return newLineParser(String(d.weight), parseFloat(String(d.weightStyle).split(',')[0]))
                    });

                    // weight update
                    _utils2['default'].conditionalTransition(weights, !owner.nodeDragging).call(weightPosition);

                    // weight exit
                    weights.exit().remove();

                    // exit
                    links.exit().remove();
                }

                inner.owner = function (value) {
                    if (!arguments.length) {
                        return owner;
                    }
                    owner = value;
                    return inner;
                };

                return inner;
            };

            module.exports = exports['default'];

        }, {"../Vector": 6, "../utils": 17, "extend": 3}],
        9: [function (require, module, exports) {
            'use strict';

            Object.defineProperty(exports, '__esModule', {
                value: true
            });

            function _interopRequireDefault(obj) {
                return obj && obj.__esModule ? obj : {'default': obj};
            }

            var _utils = require('../utils');

            var _utils2 = _interopRequireDefault(_utils);

            var _const = require('../const');

            var d3 = window.d3;

            exports['default'] = function () {
                var owner;

                function inner(selection) {
                    var nodes = selection.selectAll('g.node').data(function (d) {
                        return d.nodes;
                    }, function (d) {
                        return d.id;
                    });

                    var layout = owner.layout;

                    var g = nodes.enter().append('g').attr('class', function (d) {
                        return 'node ' + (d['class'] || '');
                    }).attr('id', function (d) {
                        return _utils2['default'].ns(d.id);
                    }).attr('transform', function (d) {
                        return _utils2['default'].transform({translate: d});
                    }).on('mouseover', function () {
                        var el = d3.select(this);
                        if (!el.over) {
                            el.style('cursor', 'pointer');
                        }
                        el.over = true;
                    }).on('mouseout', function () {
                        var el = d3.select(this);
                        if (!owner.nodeDragging) {
                            el.over = false;
                            el.style('cursor', null);
                        }
                    }).attr('opacity', 0);
                    g.transition('enter').attr('opacity', 1);
                    g.on('mousedown', mouse_down).call(layout.drag);

                    function mouse_down() {
                        var stop = window.d3.event.button || window.d3.event.ctrlKey;
                        if (stop) window.d3.event.stopImmediatePropagation();
                    }

                    var dragStart = layout.drag().on('dragstart.d3adaptor');
                    var dragEnd = layout.drag().on('dragend.d3adaptor');
                    layout.drag().on('dragstart.d3adaptor', function (d) {
                        d3.select('body').style('cursor', 'pointer');
                        d3.event.sourceEvent.stopPropagation();
                        dragNode(true, d.id);
                        owner.nodeDragging = true;
                        dragStart.apply(undefined, arguments);
                    }).on('dragend.d3adaptor', function (d) {
                        d3.select('body').style('cursor', null);
                        dragNode(false, d.id);
                        owner.nodeDragging = false;
                        dragEnd.apply(undefined, arguments);
                    });

                    g.append('circle').attr('fill', function (d) {
                        return d.color;
                    }).attr('r', function (d) {
                        return d.r;
                    });

                    function newLineParser(s, fontSize, centerY) {
                        var newS = '';
                        var lines = s.split('\n');
                        var dy = -(lines.length - 1) * 1.2 * fontSize;
                        if (centerY) dy = (dy / 2.0) + (0.46 * fontSize);
                        for (var i = 0; i < lines.length; i++) {
                            newS += "<tspan x='0px' y='" + (1.2 * fontSize * i) + "px' dy='" + dy + "px'>";
                            newS += lines[i];
                            newS += "</tspan>";
                        }
                        return newS;
                    }

                    function getLabelPosition(d, labelId) {
                        if (labelId === 1) return 'translate(' + String(-d.r * 0.71 - 2) + ', ' + String(-d.r * 0.71 - 2) + ')';
                        return 'translate(' + String(d.r * 0.71 + 2) + ', ' + String(-d.r * 0.71 - 2) + ')';
                    }

                    // inner label
                    g.append('text').classed('label', true).attr('font-family', 'Oswald').attr('text-anchor', 'middle').attr('paint-order', 'stroke').attr('stroke-linecap', 'round').attr('stroke-linejoin', 'round').attr('vector-effect', 'non-scaling-stroke').attr('stroke', function (d) {
                        return String(d.labelStyle).split(',')[2]
                    });
                    nodes.selectAll('text.label').attr('font-size', function (d) {
                        return String(d.labelStyle).split(',')[0] + 'px'
                    });
                    nodes.selectAll('text.label').attr('fill', function (d) {
                        return String(d.labelStyle).split(',')[1]
                    });
                    nodes.selectAll('text.label').each(function (d) {
                        if (String(d.labelStyle).split(',')[3] === 'True') {
                            d3.select(this).attr('stroke', String(d.labelStyle).split(',')[2]);
                        }
                    });
                    nodes.selectAll('text.label').attr('stroke-width', function (d) {
                        return String(Math.min(Math.floor((parseFloat(String(d.labelStyle).split(',')[0]) / 14.0) * 6.0), 6.0)) + 'px'
                    });
                    nodes.selectAll('text.label').html(function (d) {
                        return newLineParser(String(d.label), parseFloat(String(d.labelStyle).split(',')[0]), true)
                    });

                    // top-right label
                    g.append('text').classed('outer-top-right', true).attr('font-family', 'Oswald').attr('text-anchor', 'start').attr('paint-order', 'stroke').attr('stroke-linecap', 'round').attr('stroke-linejoin', 'round').attr('vector-effect', 'non-scaling-stroke').attr('transform', function (d) {
                        return getLabelPosition(d, 0)
                    });
                    nodes.selectAll('text.outer-top-right').attr('font-size', function (d) {
                        return String(d.topRightLabelStyle).split(',')[0] + 'px'
                    });
                    nodes.selectAll('text.outer-top-right').attr('fill', function (d) {
                        return String(d.topRightLabelStyle).split(',')[1]
                    });
                    nodes.selectAll('text.outer-top-right').attr('stroke', function (d) {
                        return String(d.topRightLabelStyle).split(',')[2]
                    });
                    nodes.selectAll('text.outer-top-right').attr('stroke-width', function (d) {
                        return String(Math.min(Math.floor((parseFloat(String(d.topRightLabelStyle).split(',')[0]) / 15.0) * 6.0), 6.0)) + 'px'
                    });
                    nodes.selectAll('text.outer-top-right').transition(500).attr('transform', function (d) {
                        return getLabelPosition(d, 0)
                    });
                    nodes.selectAll('text.outer-top-right').html(function (d) {
                        return newLineParser(String(d.topRightLabel), parseFloat(String(d.topRightLabelStyle).split(',')[0]), false)
                    });

                    // top-left label
                    g.append('text').classed('outer-top-left', true).attr('font-family', 'Oswald').attr('text-anchor', 'end').attr('paint-order', 'stroke').attr('stroke-linecap', 'round').attr('stroke-linejoin', 'round').attr('vector-effect', 'non-scaling-stroke').attr('transform', function (d) {
                        return getLabelPosition(d, 1)
                    });
                    nodes.selectAll('text.outer-top-left').attr('font-size', function (d) {
                        return String(d.topLeftLabelStyle).split(',')[0] + 'px'
                    });
                    nodes.selectAll('text.outer-top-left').attr('fill', function (d) {
                        return String(d.topLeftLabelStyle).split(',')[1]
                    });
                    nodes.selectAll('text.outer-top-left').attr('stroke', function (d) {
                        return String(d.topLeftLabelStyle).split(',')[2]
                    });
                    nodes.selectAll('text.outer-top-left').attr('stroke-width', function (d) {
                        return String(Math.min(Math.floor((parseFloat(String(d.topLeftLabelStyle).split(',')[0]) / 15.0) * 6.0), 6.0)) + 'px'
                    });
                    nodes.selectAll('text.outer-top-left').transition(500).attr('transform', function (d) {
                        return getLabelPosition(d, 1)
                    });
                    nodes.selectAll('text.outer-top-left').html(function (d) {
                        return newLineParser(String(d.topLeftLabel), parseFloat(String(d.topLeftLabelStyle).split(',')[0]), false)
                    });

                    // update
                    _utils2['default'].conditionalTransition(nodes, !owner.nodeDragging).attr('transform', function (d) {
                        return _utils2['default'].transform({
                            translate: d
                        });
                    });

                    // exit
                    nodes.exit().remove();
                }

                inner.owner = function (value) {
                    if (!arguments.length) {
                        return owner;
                    }
                    owner = value;
                    return inner;
                };

                return inner;
            };

            module.exports = exports['default'];

        }, {"../const": 7, "../utils": 17}],
        10: [function (require, module, exports) {
            'use strict';

            Object.defineProperty(exports, '__esModule', {
                value: true
            });

            function _interopRequireDefault(obj) {
                return obj && obj.__esModule ? obj : {'default': obj};
            }

            var _polyfills = require('./polyfills');

            var _polyfills2 = _interopRequireDefault(_polyfills);

// node

            var _Draw = require('./Draw');

            var _Draw2 = _interopRequireDefault(_Draw);

            var _utils = require('./utils');

            var _utils2 = _interopRequireDefault(_utils);

            var _Graph = require('./Graph');

            var _Graph2 = _interopRequireDefault(_Graph);

            var _const = require('./const');

            var _playerIndex = require('./player/index');

            var _playerIndex2 = _interopRequireDefault(_playerIndex);

            (0, _polyfills2['default'])();

            var d3 = window.d3;

            var instances = [];

            function run(options) {
                function factory(options) {
                    var el = d3.select(options.target);
                    var id = el.attr('greuler-id');
                    if (!id) {
                        id = _utils2['default'].id();
                        el.attr('greuler-id', id);
                        instances[id] = new _Draw2['default'](id, options);
                    }
                    return instances[id];
                }

                return factory(options);
            }

            run.Graph = _Graph2['default'];

            run.colors = _const.colors;

            run.player = _playerIndex2['default'];

            exports['default'] = run;
            module.exports = exports['default'];

        }, {"./Draw": 4, "./Graph": 5, "./const": 7, "./player/index": 13, "./polyfills": 14, "./utils": 17}],
        11: [function (require, module, exports) {
            'use strict';

            Object.defineProperty(exports, '__esModule', {
                value: true
            });

            var _createClass = (function () {
                function defineProperties(target, props) {
                    for (var i = 0; i < props.length; i++) {
                        var descriptor = props[i];
                        descriptor.enumerable = descriptor.enumerable || false;
                        descriptor.configurable = true;
                        if ('value' in descriptor) descriptor.writable = true;
                        Object.defineProperty(target, descriptor.key, descriptor);
                    }
                }

                return function (Constructor, protoProps, staticProps) {
                    if (protoProps) defineProperties(Constructor.prototype, protoProps);
                    if (staticProps) defineProperties(Constructor, staticProps);
                    return Constructor;
                };
            })();

            function _classCallCheck(instance, Constructor) {
                if (!(instance instanceof Constructor)) {
                    throw new TypeError('Cannot call a class as a function');
                }
            }

            var Player = (function () {
                function Player(actions, speed) {
                    _classCallCheck(this, Player);

                    this.index = 0;
                    this.speed = speed;
                    this.actions = actions;

                    // states
                    this.timer = null;
                }

                _createClass(Player, [{
                    key: 'play',
                    value: function play() {
                        if (this.index < this.actions.length) {
                            this.actions[this.index++]();
                            this.timer = setTimeout(this.play.bind(this), this.speed);
                        }
                    }
                }, {
                    key: 'pause',
                    value: function pause() {
                        clearTimeout(this.timer);
                    }
                }, {
                    key: 'stop',
                    value: function stop() {
                        this.pause();
                        this.index = 0;
                    }
                }]);

                return Player;
            })();

            exports['default'] = Player;
            module.exports = exports['default'];

        }, {}],
        12: [function (require, module, exports) {
            'use strict';

            Object.defineProperty(exports, '__esModule', {
                value: true
            });

            var _createClass = (function () {
                function defineProperties(target, props) {
                    for (var i = 0; i < props.length; i++) {
                        var descriptor = props[i];
                        descriptor.enumerable = descriptor.enumerable || false;
                        descriptor.configurable = true;
                        if ('value' in descriptor) descriptor.writable = true;
                        Object.defineProperty(target, descriptor.key, descriptor);
                    }
                }

                return function (Constructor, protoProps, staticProps) {
                    if (protoProps) defineProperties(Constructor.prototype, protoProps);
                    if (staticProps) defineProperties(Constructor, staticProps);
                    return Constructor;
                };
            })();

            function _classCallCheck(instance, Constructor) {
                if (!(instance instanceof Constructor)) {
                    throw new TypeError('Cannot call a class as a function');
                }
            }

            var Generator = (function () {
                function Generator(instance, speed) {
                    _classCallCheck(this, Generator);

                    this.instance = instance;
                    this.speed = speed || instance.options.animationTime;
                    this.fn = null;
                    this.timer = null;
                }

                _createClass(Generator, [{
                    key: 'run',
                    value: function run(fn) {
                        this.fn = fn(this.instance);
                        this.play();
                    }
                }, {
                    key: 'runAnimation',
                    value: function runAnimation(animation) {
                        if (Array.isArray(animation)) {
                            return animation.forEach(this.runAnimation, this);
                        }

                        if (typeof animation === 'function') {
                            return animation(this.instance);
                        }

                        var type = this.instance[animation.type];
                        return type[animation.op].apply(type, animation.args || []);
                    }
                }, {
                    key: 'play',
                    value: function play(value) {
                        var self = this;
                        var next = this.fn.next(value);
                        if (!next.done) {
                            var delay = this.speed;
                            var runAnimationValue = this.runAnimation(next.value);
                            if (runAnimationValue && typeof runAnimationValue === 'object') {
                                if (typeof runAnimationValue.delay === 'number') {
                                    delay = runAnimationValue.delay;
                                }
                            }

                            this.timer = window.requestTimeout(function () {
                                self.play(next.value);
                            }, delay);
                        }
                    }
                }, {
                    key: 'pause',
                    value: function pause() {
                        window.clearRequestTimeout(this.timer);
                    }
                }]);

                return Generator;
            })();

            exports['default'] = Generator;
            module.exports = exports['default'];

        }, {}],
        13: [function (require, module, exports) {
            'use strict';

            Object.defineProperty(exports, '__esModule', {
                value: true
            });

            function _interopRequireDefault(obj) {
                return obj && obj.__esModule ? obj : {'default': obj};
            }

            var _Fixed = require('./Fixed');

            var _Fixed2 = _interopRequireDefault(_Fixed);

            var _Generator = require('./Generator');

            var _Generator2 = _interopRequireDefault(_Generator);

            exports['default'] = {
                FixedInterval: _Fixed2['default'],
                Generator: _Generator2['default']
            };
            module.exports = exports['default'];

        }, {"./Fixed": 11, "./Generator": 12}],
        14: [function (require, module, exports) {
            'use strict';

            Object.defineProperty(exports, '__esModule', {
                value: true
            });

            exports['default'] = function () {
                (function (doc, proto) {
                    try {
                        // check if browser supports :scope natively
                        doc.querySelector(':scope body');
                    } catch (err) {
                        // polyfill native methods if it doesn't
                        ['querySelector', 'querySelectorAll'].forEach(function (method) {
                            var native = proto[method];
                            proto[method] = function (selectors) {
                                if (/(^|,)\s*:scope/.test(selectors)) {
                                    // only if selectors contains :scope
                                    var id = this.id; // remember current element id
                                    this.id = 'ID_' + Date.now(); // assign new unique id
                                    selectors = selectors.replace(/((^|,)\s*):scope/g, '$1#' + this.id); // replace :scope with #ID
                                    var result = doc[method](selectors);
                                    this.id = id; // restore previous id
                                    return result;
                                } else {
                                    return native.call(this, selectors); // use native code for other selectors
                                }
                            };
                        });
                    }
                })(window.document, Element.prototype);

                // from https://gist.github.com/joelambert/1002116
                //
                // requestAnimationFrame() shim by Paul Irish
                // http://paulirish.com/2011/requestanimationframe-for-smart-animating/
                window.requestAnimFrame = (function () {
                    return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback, element) {
                        window.setTimeout(callback, 1000 / 60);
                    };
                })();

                /**
                 * Behaves the same as setTimeout except uses requestAnimationFrame() where possible for better performance
                 * @param {function} fn The callback function
                 * @param {int} delay The delay in milliseconds
                 */
                window.requestTimeout = function (fn, delay) {
                    if (!window.requestAnimationFrame && !window.webkitRequestAnimationFrame && !(window.mozRequestAnimationFrame && window.mozCancelRequestAnimationFrame) && // Firefox 5 ships without cancel support
                        !window.oRequestAnimationFrame && !window.msRequestAnimationFrame) return window.setTimeout(fn, delay);

                    var start = new Date().getTime();
                    var handle = {};

                    function loop() {
                        var current = new Date().getTime(),
                            delta = current - start;

                        delta >= delay ? fn.call() : handle.value = requestAnimFrame(loop);
                    }

                    handle.value = requestAnimFrame(loop);
                    return handle;
                };

                /**
                 * Behaves the same as clearTimeout except uses cancelRequestAnimationFrame() where possible for better performance
                 * @param {int|object} handle The callback function
                 */
                window.clearRequestTimeout = function (handle) {
                    window.cancelAnimationFrame ? window.cancelAnimationFrame(handle.value) : window.webkitCancelAnimationFrame ? window.webkitCancelAnimationFrame(handle.value) : window.webkitCancelRequestAnimationFrame ? window.webkitCancelRequestAnimationFrame(handle.value) : /* Support for legacy API */
                        window.mozCancelRequestAnimationFrame ? window.mozCancelRequestAnimationFrame(handle.value) : window.oCancelRequestAnimationFrame ? window.oCancelRequestAnimationFrame(handle.value) : window.msCancelRequestAnimationFrame ? window.msCancelRequestAnimationFrame(handle.value) : clearTimeout(handle);
                };
                /*eslint-enable */
            };

            module.exports = exports['default'];

            /*eslint-disable */
            /* function */
            /* DOMElement */

        }, {}],
        15: [function (require, module, exports) {
            'use strict';

            Object.defineProperty(exports, '__esModule', {
                value: true
            });

            var _createClass = (function () {
                function defineProperties(target, props) {
                    for (var i = 0; i < props.length; i++) {
                        var descriptor = props[i];
                        descriptor.enumerable = descriptor.enumerable || false;
                        descriptor.configurable = true;
                        if ('value' in descriptor) descriptor.writable = true;
                        Object.defineProperty(target, descriptor.key, descriptor);
                    }
                }

                return function (Constructor, protoProps, staticProps) {
                    if (protoProps) defineProperties(Constructor.prototype, protoProps);
                    if (staticProps) defineProperties(Constructor, staticProps);
                    return Constructor;
                };
            })();

            function _interopRequireDefault(obj) {
                return obj && obj.__esModule ? obj : {'default': obj};
            }

            function _classCallCheck(instance, Constructor) {
                if (!(instance instanceof Constructor)) {
                    throw new TypeError('Cannot call a class as a function');
                }
            }

            var _utils = require('../utils');

            var _utils2 = _interopRequireDefault(_utils);

            var _extend = require('extend');

            var _extend2 = _interopRequireDefault(_extend);

            var ElementSelector = (function () {
                function ElementSelector(owner) {
                    _classCallCheck(this, ElementSelector);

                    this.owner = owner;
                    this.graph = owner.graph;
                    this.defaultStyleOptions = {};
                }

                _createClass(ElementSelector, [{
                    key: 'getDefaultStyleOptions',
                    value: function getDefaultStyleOptions() {
                        return (0, _extend2['default'])({
                            duration: this.getAnimationTime(),
                            stroke: '#E74C3C'
                        }, this.defaultStyleOptions);
                    }
                }, {
                    key: 'getStyleOptions',
                    value: function getStyleOptions(options) {
                        return (0, _extend2['default'])({}, this.getDefaultStyleOptions(), options);
                    }
                }, {
                    key: 'getAnimationTime',
                    value: function getAnimationTime() {
                        return this.owner.options.animationTime;
                    }

                    /**
                     * Given a collection of elements returned by the Graph class this methods returns
                     * the d3 selection that for all those objects
                     *
                     * @param {Object[]|Object} els An array of edges/nodes or a single edge/node
                     * @return {d3_selection}
                     */
                }, {
                    key: 'select',
                    value: function select(els) {
                        if (!Array.isArray(els)) {
                            els = [els];
                        }
                        if (!els.length) {
                            els.push({id: -1});
                        }
                        els = els.filter(Boolean);
                        return this.owner.root.selectAll(els.map(function (e) {
                            return '#' + _utils2['default'].ns(e.id);
                        }).join(', '));
                    }

                    /**
                     * Selects the path inside the tag <g> that represents an edge
                     *
                     * @param {d3_selection} selection
                     */
                }, {
                    key: 'innerEdgeSelector',
                    value: function innerEdgeSelector(selection) {
                        return selection.selectAll('path.base');
                    }

                    /**
                     * Selects the circle inside the tag <g> that represents a node
                     *
                     * @param {d3_selection} selection
                     */
                }, {
                    key: 'innerNodeSelector',
                    value: function innerNodeSelector(selection) {
                        return selection.selectAll('circle');
                    }
                }]);

                return ElementSelector;
            })();

            exports['default'] = ElementSelector;
            module.exports = exports['default'];

        }, {"../utils": 17, "extend": 3}],
        16: [function (require, module, exports) {
            'use strict';

            Object.defineProperty(exports, '__esModule', {
                value: true
            });

            var _createClass = (function () {
                function defineProperties(target, props) {
                    for (var i = 0; i < props.length; i++) {
                        var descriptor = props[i];
                        descriptor.enumerable = descriptor.enumerable || false;
                        descriptor.configurable = true;
                        if ('value' in descriptor) descriptor.writable = true;
                        Object.defineProperty(target, descriptor.key, descriptor);
                    }
                }

                return function (Constructor, protoProps, staticProps) {
                    if (protoProps) defineProperties(Constructor.prototype, protoProps);
                    if (staticProps) defineProperties(Constructor, staticProps);
                    return Constructor;
                };
            })();

            var _get = function get(_x2, _x3, _x4) {
                var _again = true;
                _function: while (_again) {
                    var object = _x2, property = _x3, receiver = _x4;
                    desc = parent = getter = undefined;
                    _again = false;
                    if (object === null) object = Function.prototype;
                    var desc = Object.getOwnPropertyDescriptor(object, property);
                    if (desc === undefined) {
                        var parent = Object.getPrototypeOf(object);
                        if (parent === null) {
                            return undefined;
                        } else {
                            _x2 = parent;
                            _x3 = property;
                            _x4 = receiver;
                            _again = true;
                            continue _function;
                        }
                    } else if ('value' in desc) {
                        return desc.value;
                    } else {
                        var getter = desc.get;
                        if (getter === undefined) {
                            return undefined;
                        }
                        return getter.call(receiver);
                    }
                }
            };

            function _interopRequireDefault(obj) {
                return obj && obj.__esModule ? obj : {'default': obj};
            }

            function _classCallCheck(instance, Constructor) {
                if (!(instance instanceof Constructor)) {
                    throw new TypeError('Cannot call a class as a function');
                }
            }

            function _inherits(subClass, superClass) {
                if (typeof superClass !== 'function' && superClass !== null) {
                    throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass);
                }
                subClass.prototype = Object.create(superClass && superClass.prototype, {
                    constructor: {
                        value: subClass,
                        enumerable: false,
                        writable: true,
                        configurable: true
                    }
                });
                if (superClass) subClass.__proto__ = superClass;
            }

            var _extend = require('extend');

            var _extend2 = _interopRequireDefault(_extend);

            var _Graph2 = require('./Graph');

            var _Graph3 = _interopRequireDefault(_Graph2);

            var d3 = window.d3;

            var HIGHLIGHT = 'highlight';

            var GreulerDefaultTransition = (function (_Graph) {
                _inherits(GreulerDefaultTransition, _Graph);

                function GreulerDefaultTransition() {
                    _classCallCheck(this, GreulerDefaultTransition);

                    _get(Object.getPrototypeOf(GreulerDefaultTransition.prototype), 'constructor', this).apply(this, arguments);
                }

                _createClass(GreulerDefaultTransition, [{
                    key: 'getEdges',

                    /**
                     * Gets all the edges of the graph
                     *
                     * @returns {d3_selection}
                     */
                    value: function getEdges() {
                        return this.innerEdgeSelector(this.select(this.graph.edges));
                    }

                    /**
                     * Gets all the nodes of the graph
                     *
                     * @returns {d3_selection}
                     */
                }, {
                    key: 'getNodes',
                    value: function getNodes() {
                        return this.innerNodeSelector(this.select(this.graph.nodes));
                    }

                    /**
                     * Highlights a node temporarily, it consists of two
                     * chained transitions
                     *
                     * - increase the radius to 1.5x the original `r` value
                     * - decrease the radius to the original `r` value
                     *
                     * @param {d3_selection} selection
                     * @param {Object} options
                     * @returns {d3_transition}
                     */
                }, {
                    key: 'doTemporalHighlightNode',
                    value: function doTemporalHighlightNode(selection, options) {
                        if ('size' in options) {
                            this.innerNodeSelector(selection).transition('highlight_node_size').duration(this.getAnimationTime() / 2).attr('r', options.size).transition('highlight_node_size').duration(this.getAnimationTime() / 2).attr('r', function (d) {
                                return d.r
                            });
                        }
                        if ('color' in options) {
                            this.innerNodeSelector(selection).transition('highlight_node_color').duration(this.getAnimationTime() / 2).attr('fill', options.color).transition('highlight_node_color').duration(this.getAnimationTime() / 2).attr('fill', function (d) {
                                return d.color
                            });

                            selection.selectAll('text.label').transition('highlight_node_outline').duration(this.getAnimationTime() / 2).attr('stroke', function (d) {
                                return String(d.labelStyle).split(',')[3] === 'False' ? options.color : String(d.labelStyle).split(',')[2]
                            }).transition('highlight_node_outline').duration(this.getAnimationTime() / 2).attr('stroke', function (d) {
                                return String(d.labelStyle).split(',')[3] === 'False' ? d.color : String(d.labelStyle).split(',')[2]
                            });
                        }
                        return true;
                    }

                    /**
                     * Highlights an edge temporarily, it consists of two
                     * chained transitions
                     *
                     * - change the stroke of the `path` that represents the edge to
                     * `options.stroke`
                     * - change the stroke to the original value
                     *
                     * @param {d3_selection} selection
                     * @param {Object} options
                     * @returns {d3_transition}
                     */
                }, {
                    key: 'doTemporalHighlightEdges',
                    value: function doTemporalHighlightEdges(selection, options) {
                        if ('width' in options) {
                            this.innerEdgeSelector(selection).transition('highlight_edge_width').duration(this.getAnimationTime() / 2).attr('stroke-width', options.width).transition('highlight_edge_width').duration(this.getAnimationTime() / 2).attr('stroke-width', function (d) {
                                return d.lineWidth
                            });
                        }
                        if ('color' in options) {
                            this.innerEdgeSelector(selection).transition('highlight_edge_color').duration(this.getAnimationTime() / 2).attr('stroke', options.color).transition('highlight_edge_color').duration(this.getAnimationTime() / 2).attr('stroke', function (d) {
                                return d.stroke
                            });
                        }
                        return true;
                    }

                    /**
                     * Edge traversal animation, it animates a hidden path giving the impression
                     * of movement, if source is given then it will always start the animation
                     * from the node `source` even if the edge is an incoming edge
                     *
                     * @param {d3_selection} selection
                     * @param {config} options
                     * @param {number} [source=-1]
                     * @returns {d3_transition}
                     */
                }, {
                    key: 'traverseEdgeWithDirection',
                    value: function traverseEdgeWithDirection(selection, options) {
                        var source = arguments.length <= 2 || arguments[2] === undefined ? -1 : arguments[2];

                        return selection.selectAll('path.traversal').each(function () {
                            var el = d3.select(this);
                            var l = this.getTotalLength();
                            el.attr('stroke', options.stroke).attr('stroke-dasharray', l + ' ' + l).attr('stroke-dashoffset', l).attr('opacity', 1);
                        }).transition('dasharray').duration(options.duration).attr('stroke-dashoffset', function (d) {
                            var length = this.getTotalLength();
                            var twiceLength = length * 2;
                            var lengthToMove = 0;
                            if (source !== -1) {
                                if (d.target.id === source) {
                                    lengthToMove = twiceLength;
                                }
                            }

                            if (options.reverse) {
                                lengthToMove = twiceLength - lengthToMove;
                            }

                            return lengthToMove;
                        }).attr('opacity', 0).each('end', function () {
                            var el = d3.select(this);
                            el.attr('stroke-dasharray', null).attr('stroke-dashoffset', null).attr('opacity', 0);
                        });
                    }
                }, {
                    key: 'traverseEdges',
                    value: function traverseEdges(selection, options, source) {
                        options = (0, _extend2['default'])({
                            keepStroke: true,
                            reverse: false
                        }, this.getStyleOptions(), options);

                        selection.call(this.traverseEdgeWithDirection, options, source);
                        if (options.keepStroke) {
                            this.innerEdgeSelector(selection).transition('update').duration(options.duration).attr('stroke', options.stroke);
                        }
                        return this.innerEdgeSelector(selection);
                    }
                }, {
                    key: 'getNode',
                    value: function getNode(node) {
                        return this.innerNodeSelector(this.select(this.graph.getNode(node)));
                    }
                }, {
                    key: 'getNodeOuter',
                    value: function getNodeOuter(node) {
                        return this.select(this.graph.getNode(node));
                    }
                }, {
                    key: 'getEdge',
                    value: function getEdge(edge) {
                        return this.innerEdgeSelector(this.select(this.graph.getEdge(edge)));
                    }
                }, {
                    key: 'getEdgeOuter',
                    value: function getEdgeOuter(edge) {
                        return this.select(this.graph.getEdge(edge));
                    }

                    // temporal highlight

                }, {
                    key: 'highlightNode',
                    value: function highlightNode(node, options) {
                        return this.doTemporalHighlightNode(this.select(this.graph.getNode(node)), this.getStyleOptions(options));
                    }
                }, {
                    key: 'highlightEdge',
                    value: function highlightEdge(edge, options) {
                        return this.doTemporalHighlightEdges(this.select(this.graph.getEdge(edge)), this.getStyleOptions(options));
                    }
                }, {
                    key: 'highlightIncidentEdges',
                    value: function highlightIncidentEdges(node, options) {
                        return this.doTemporalHighlightEdges(this.select(this.graph.getIncidentEdges(node)), this.getStyleOptions(options));
                    }
                }, {
                    key: 'highlightOutgoingEdges',
                    value: function highlightOutgoingEdges(node, options) {
                        return this.doTemporalHighlightEdges(this.select(this.graph.getOutgoingEdges(node)), this.getStyleOptions(options));
                    }
                }, {
                    key: 'highlightIncomingEdges',
                    value: function highlightIncomingEdges(node, options) {
                        return this.doTemporalHighlightEdges(this.select(this.graph.getIncomingEdges(node)), this.getStyleOptions(options));
                    }

                    // traversal of an edge given a node

                }, {
                    key: 'traverseOutgoingEdges',
                    value: function traverseOutgoingEdges(node, options) {
                        return this.traverseEdges(this.select(this.graph.getOutgoingEdges(node)), this.getStyleOptions(options));
                    }
                }, {
                    key: 'traverseIncomingEdges',
                    value: function traverseIncomingEdges(node, options) {
                        return this.traverseEdges(this.select(this.graph.getIncomingEdges(node)), this.getStyleOptions(options));
                    }
                }, {
                    key: 'traverseIncidentEdges',
                    value: function traverseIncidentEdges(node, options) {
                        return this.traverseEdges(this.select(this.graph.getIncidentEdges(node)), this.getStyleOptions(options));
                    }

                    // traversal of an edge between two nodes

                }, {
                    key: 'traverseEdgesBetween',
                    value: function traverseEdgesBetween(edge, options) {
                        return this.traverseEdges(this.select(this.graph.getEdgesBetween(edge)), this.getStyleOptions(options), edge.source);
                    }
                }, {
                    key: 'traverseAllEdgesBetween',
                    value: function traverseAllEdgesBetween(edge, options) {
                        return this.traverseEdges(this.select(this.graph.getAllEdgesBetween(edge)), this.getStyleOptions(options), edge.source);
                    }

                }, {
                    key: 'traverseEdge',
                    value: function traverseEdge(edge, options, source) {
                        return this.traverseEdges(this.select(this.graph.getEdge(edge)), this.getStyleOptions(options), source);
                    }
                }]);

                return GreulerDefaultTransition;
            })(_Graph3['default']);

            exports['default'] = GreulerDefaultTransition;
            module.exports = exports['default'];

        }, {"./Graph": 15, "extend": 3}],
        17: [function (require, module, exports) {
            'use strict';

            Object.defineProperty(exports, '__esModule', {
                value: true
            });

            function _interopRequireDefault(obj) {
                return obj && obj.__esModule ? obj : {'default': obj};
            }

            var _computeLcg = require('compute-lcg');

            var _computeLcg2 = _interopRequireDefault(_computeLcg);

            var rand = (0, _computeLcg2['default'])(1);

            exports['default'] = {
                id: function id() {
                    var n = rand();
                    var letter = String.fromCharCode(Math.floor(n * 26) + 97);
                    return letter + n.toString(16).substr(2);
                },

                transform: function transform(o) {
                    var str = '';
                    if ('translate' in o) {
                        str += ' translate(' + o.translate.x + ', ' + o.translate.y + ')';
                    }
                    if ('rotate' in o) {
                        str += ' rotate(' + o.rotate + ')';
                    }
                    if ('scale' in o) {
                        str += ' scale(' + o.scale + ')';
                    }
                    return str;
                },

                transition: function transition(selection) {
                    return selection.transition('layout').duration(300).ease('linear');
                },

                conditionalTransition: function conditionalTransition(el, condition) {
                    if (condition) {
                        return this.transition(el);
                    }
                    return el;
                },

                ns: function ns(str) {
                    return 'greuler-' + str;
                }
            };
            module.exports = exports['default'];

        }, {"compute-lcg": 2}]
    }, {}, [10])(10)
});
