cytoscape
Version:
Graph theory (a.k.a. network) library for analysis and visualisation
1,975 lines (1,651 loc) • 873 kB
JavaScript
/**
* Copyright (c) 2016-2022, The Cytoscape Consortium.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the “Software”), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
'use strict';
var debounce = require('lodash/debounce');
var Heap = require('heap');
var get = require('lodash/get');
var set = require('lodash/set');
var toPath = require('lodash/toPath');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var debounce__default = /*#__PURE__*/_interopDefaultLegacy(debounce);
var Heap__default = /*#__PURE__*/_interopDefaultLegacy(Heap);
var get__default = /*#__PURE__*/_interopDefaultLegacy(get);
var set__default = /*#__PURE__*/_interopDefaultLegacy(set);
var toPath__default = /*#__PURE__*/_interopDefaultLegacy(toPath);
function _typeof(obj) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
}, _typeof(obj);
}
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a 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);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
Object.defineProperty(Constructor, "prototype", {
writable: false
});
return Constructor;
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function _slicedToArray(arr, i) {
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
}
function _arrayWithHoles(arr) {
if (Array.isArray(arr)) return arr;
}
function _iterableToArrayLimit(arr, i) {
var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
if (_i == null) return;
var _arr = [];
var _n = true;
var _d = false;
var _s, _e;
try {
for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"] != null) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;
}
function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
var window$1 = typeof window === 'undefined' ? null : window; // eslint-disable-line no-undef
var navigator = window$1 ? window$1.navigator : null;
window$1 ? window$1.document : null;
var typeofstr = _typeof('');
var typeofobj = _typeof({});
var typeoffn = _typeof(function () {});
var typeofhtmlele = typeof HTMLElement === "undefined" ? "undefined" : _typeof(HTMLElement);
var instanceStr = function instanceStr(obj) {
return obj && obj.instanceString && fn$6(obj.instanceString) ? obj.instanceString() : null;
};
var string = function string(obj) {
return obj != null && _typeof(obj) == typeofstr;
};
var fn$6 = function fn(obj) {
return obj != null && _typeof(obj) === typeoffn;
};
var array = function array(obj) {
return !elementOrCollection(obj) && (Array.isArray ? Array.isArray(obj) : obj != null && obj instanceof Array);
};
var plainObject = function plainObject(obj) {
return obj != null && _typeof(obj) === typeofobj && !array(obj) && obj.constructor === Object;
};
var object = function object(obj) {
return obj != null && _typeof(obj) === typeofobj;
};
var number$1 = function number(obj) {
return obj != null && _typeof(obj) === _typeof(1) && !isNaN(obj);
};
var integer = function integer(obj) {
return number$1(obj) && Math.floor(obj) === obj;
};
var htmlElement = function htmlElement(obj) {
if ('undefined' === typeofhtmlele) {
return undefined;
} else {
return null != obj && obj instanceof HTMLElement;
}
};
var elementOrCollection = function elementOrCollection(obj) {
return element(obj) || collection(obj);
};
var element = function element(obj) {
return instanceStr(obj) === 'collection' && obj._private.single;
};
var collection = function collection(obj) {
return instanceStr(obj) === 'collection' && !obj._private.single;
};
var core = function core(obj) {
return instanceStr(obj) === 'core';
};
var stylesheet = function stylesheet(obj) {
return instanceStr(obj) === 'stylesheet';
};
var event = function event(obj) {
return instanceStr(obj) === 'event';
};
var emptyString = function emptyString(obj) {
if (obj === undefined || obj === null) {
// null is empty
return true;
} else if (obj === '' || obj.match(/^\s+$/)) {
return true; // empty string is empty
}
return false; // otherwise, we don't know what we've got
};
var domElement = function domElement(obj) {
if (typeof HTMLElement === 'undefined') {
return false; // we're not in a browser so it doesn't matter
} else {
return obj instanceof HTMLElement;
}
};
var boundingBox = function boundingBox(obj) {
return plainObject(obj) && number$1(obj.x1) && number$1(obj.x2) && number$1(obj.y1) && number$1(obj.y2);
};
var promise = function promise(obj) {
return object(obj) && fn$6(obj.then);
};
var ms = function ms() {
return navigator && navigator.userAgent.match(/msie|trident|edge/i);
}; // probably a better way to detect this...
var memoize = function memoize(fn, keyFn) {
if (!keyFn) {
keyFn = function keyFn() {
if (arguments.length === 1) {
return arguments[0];
} else if (arguments.length === 0) {
return 'undefined';
}
var args = [];
for (var i = 0; i < arguments.length; i++) {
args.push(arguments[i]);
}
return args.join('$');
};
}
var memoizedFn = function memoizedFn() {
var self = this;
var args = arguments;
var ret;
var k = keyFn.apply(self, args);
var cache = memoizedFn.cache;
if (!(ret = cache[k])) {
ret = cache[k] = fn.apply(self, args);
}
return ret;
};
memoizedFn.cache = {};
return memoizedFn;
};
var camel2dash = memoize(function (str) {
return str.replace(/([A-Z])/g, function (v) {
return '-' + v.toLowerCase();
});
});
var dash2camel = memoize(function (str) {
return str.replace(/(-\w)/g, function (v) {
return v[1].toUpperCase();
});
});
var prependCamel = memoize(function (prefix, str) {
return prefix + str[0].toUpperCase() + str.substring(1);
}, function (prefix, str) {
return prefix + '$' + str;
});
var capitalize = function capitalize(str) {
if (emptyString(str)) {
return str;
}
return str.charAt(0).toUpperCase() + str.substring(1);
};
var number = '(?:[-+]?(?:(?:\\d+|\\d*\\.\\d+)(?:[Ee][+-]?\\d+)?))';
var rgba = 'rgb[a]?\\((' + number + '[%]?)\\s*,\\s*(' + number + '[%]?)\\s*,\\s*(' + number + '[%]?)(?:\\s*,\\s*(' + number + '))?\\)';
var rgbaNoBackRefs = 'rgb[a]?\\((?:' + number + '[%]?)\\s*,\\s*(?:' + number + '[%]?)\\s*,\\s*(?:' + number + '[%]?)(?:\\s*,\\s*(?:' + number + '))?\\)';
var hsla = 'hsl[a]?\\((' + number + ')\\s*,\\s*(' + number + '[%])\\s*,\\s*(' + number + '[%])(?:\\s*,\\s*(' + number + '))?\\)';
var hslaNoBackRefs = 'hsl[a]?\\((?:' + number + ')\\s*,\\s*(?:' + number + '[%])\\s*,\\s*(?:' + number + '[%])(?:\\s*,\\s*(?:' + number + '))?\\)';
var hex3 = '\\#[0-9a-fA-F]{3}';
var hex6 = '\\#[0-9a-fA-F]{6}';
var ascending = function ascending(a, b) {
if (a < b) {
return -1;
} else if (a > b) {
return 1;
} else {
return 0;
}
};
var descending = function descending(a, b) {
return -1 * ascending(a, b);
};
var extend = Object.assign != null ? Object.assign.bind(Object) : function (tgt) {
var args = arguments;
for (var i = 1; i < args.length; i++) {
var obj = args[i];
if (obj == null) {
continue;
}
var keys = Object.keys(obj);
for (var j = 0; j < keys.length; j++) {
var k = keys[j];
tgt[k] = obj[k];
}
}
return tgt;
};
var hex2tuple = function hex2tuple(hex) {
if (!(hex.length === 4 || hex.length === 7) || hex[0] !== '#') {
return;
}
var shortHex = hex.length === 4;
var r, g, b;
var base = 16;
if (shortHex) {
r = parseInt(hex[1] + hex[1], base);
g = parseInt(hex[2] + hex[2], base);
b = parseInt(hex[3] + hex[3], base);
} else {
r = parseInt(hex[1] + hex[2], base);
g = parseInt(hex[3] + hex[4], base);
b = parseInt(hex[5] + hex[6], base);
}
return [r, g, b];
}; // get [r, g, b, a] from hsl(0, 0, 0) or hsla(0, 0, 0, 0)
var hsl2tuple = function hsl2tuple(hsl) {
var ret;
var h, s, l, a, r, g, b;
function hue2rgb(p, q, t) {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p + (q - p) * 6 * t;
if (t < 1 / 2) return q;
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p;
}
var m = new RegExp('^' + hsla + '$').exec(hsl);
if (m) {
// get hue
h = parseInt(m[1]);
if (h < 0) {
h = (360 - -1 * h % 360) % 360;
} else if (h > 360) {
h = h % 360;
}
h /= 360; // normalise on [0, 1]
s = parseFloat(m[2]);
if (s < 0 || s > 100) {
return;
} // saturation is [0, 100]
s = s / 100; // normalise on [0, 1]
l = parseFloat(m[3]);
if (l < 0 || l > 100) {
return;
} // lightness is [0, 100]
l = l / 100; // normalise on [0, 1]
a = m[4];
if (a !== undefined) {
a = parseFloat(a);
if (a < 0 || a > 1) {
return;
} // alpha is [0, 1]
} // now, convert to rgb
// code from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
if (s === 0) {
r = g = b = Math.round(l * 255); // achromatic
} else {
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
r = Math.round(255 * hue2rgb(p, q, h + 1 / 3));
g = Math.round(255 * hue2rgb(p, q, h));
b = Math.round(255 * hue2rgb(p, q, h - 1 / 3));
}
ret = [r, g, b, a];
}
return ret;
}; // get [r, g, b, a] from rgb(0, 0, 0) or rgba(0, 0, 0, 0)
var rgb2tuple = function rgb2tuple(rgb) {
var ret;
var m = new RegExp('^' + rgba + '$').exec(rgb);
if (m) {
ret = [];
var isPct = [];
for (var i = 1; i <= 3; i++) {
var channel = m[i];
if (channel[channel.length - 1] === '%') {
isPct[i] = true;
}
channel = parseFloat(channel);
if (isPct[i]) {
channel = channel / 100 * 255; // normalise to [0, 255]
}
if (channel < 0 || channel > 255) {
return;
} // invalid channel value
ret.push(Math.floor(channel));
}
var atLeastOneIsPct = isPct[1] || isPct[2] || isPct[3];
var allArePct = isPct[1] && isPct[2] && isPct[3];
if (atLeastOneIsPct && !allArePct) {
return;
} // must all be percent values if one is
var alpha = m[4];
if (alpha !== undefined) {
alpha = parseFloat(alpha);
if (alpha < 0 || alpha > 1) {
return;
} // invalid alpha value
ret.push(alpha);
}
}
return ret;
};
var colorname2tuple = function colorname2tuple(color) {
return colors[color.toLowerCase()];
};
var color2tuple = function color2tuple(color) {
return (array(color) ? color : null) || colorname2tuple(color) || hex2tuple(color) || rgb2tuple(color) || hsl2tuple(color);
};
var colors = {
// special colour names
transparent: [0, 0, 0, 0],
// NB alpha === 0
// regular colours
aliceblue: [240, 248, 255],
antiquewhite: [250, 235, 215],
aqua: [0, 255, 255],
aquamarine: [127, 255, 212],
azure: [240, 255, 255],
beige: [245, 245, 220],
bisque: [255, 228, 196],
black: [0, 0, 0],
blanchedalmond: [255, 235, 205],
blue: [0, 0, 255],
blueviolet: [138, 43, 226],
brown: [165, 42, 42],
burlywood: [222, 184, 135],
cadetblue: [95, 158, 160],
chartreuse: [127, 255, 0],
chocolate: [210, 105, 30],
coral: [255, 127, 80],
cornflowerblue: [100, 149, 237],
cornsilk: [255, 248, 220],
crimson: [220, 20, 60],
cyan: [0, 255, 255],
darkblue: [0, 0, 139],
darkcyan: [0, 139, 139],
darkgoldenrod: [184, 134, 11],
darkgray: [169, 169, 169],
darkgreen: [0, 100, 0],
darkgrey: [169, 169, 169],
darkkhaki: [189, 183, 107],
darkmagenta: [139, 0, 139],
darkolivegreen: [85, 107, 47],
darkorange: [255, 140, 0],
darkorchid: [153, 50, 204],
darkred: [139, 0, 0],
darksalmon: [233, 150, 122],
darkseagreen: [143, 188, 143],
darkslateblue: [72, 61, 139],
darkslategray: [47, 79, 79],
darkslategrey: [47, 79, 79],
darkturquoise: [0, 206, 209],
darkviolet: [148, 0, 211],
deeppink: [255, 20, 147],
deepskyblue: [0, 191, 255],
dimgray: [105, 105, 105],
dimgrey: [105, 105, 105],
dodgerblue: [30, 144, 255],
firebrick: [178, 34, 34],
floralwhite: [255, 250, 240],
forestgreen: [34, 139, 34],
fuchsia: [255, 0, 255],
gainsboro: [220, 220, 220],
ghostwhite: [248, 248, 255],
gold: [255, 215, 0],
goldenrod: [218, 165, 32],
gray: [128, 128, 128],
grey: [128, 128, 128],
green: [0, 128, 0],
greenyellow: [173, 255, 47],
honeydew: [240, 255, 240],
hotpink: [255, 105, 180],
indianred: [205, 92, 92],
indigo: [75, 0, 130],
ivory: [255, 255, 240],
khaki: [240, 230, 140],
lavender: [230, 230, 250],
lavenderblush: [255, 240, 245],
lawngreen: [124, 252, 0],
lemonchiffon: [255, 250, 205],
lightblue: [173, 216, 230],
lightcoral: [240, 128, 128],
lightcyan: [224, 255, 255],
lightgoldenrodyellow: [250, 250, 210],
lightgray: [211, 211, 211],
lightgreen: [144, 238, 144],
lightgrey: [211, 211, 211],
lightpink: [255, 182, 193],
lightsalmon: [255, 160, 122],
lightseagreen: [32, 178, 170],
lightskyblue: [135, 206, 250],
lightslategray: [119, 136, 153],
lightslategrey: [119, 136, 153],
lightsteelblue: [176, 196, 222],
lightyellow: [255, 255, 224],
lime: [0, 255, 0],
limegreen: [50, 205, 50],
linen: [250, 240, 230],
magenta: [255, 0, 255],
maroon: [128, 0, 0],
mediumaquamarine: [102, 205, 170],
mediumblue: [0, 0, 205],
mediumorchid: [186, 85, 211],
mediumpurple: [147, 112, 219],
mediumseagreen: [60, 179, 113],
mediumslateblue: [123, 104, 238],
mediumspringgreen: [0, 250, 154],
mediumturquoise: [72, 209, 204],
mediumvioletred: [199, 21, 133],
midnightblue: [25, 25, 112],
mintcream: [245, 255, 250],
mistyrose: [255, 228, 225],
moccasin: [255, 228, 181],
navajowhite: [255, 222, 173],
navy: [0, 0, 128],
oldlace: [253, 245, 230],
olive: [128, 128, 0],
olivedrab: [107, 142, 35],
orange: [255, 165, 0],
orangered: [255, 69, 0],
orchid: [218, 112, 214],
palegoldenrod: [238, 232, 170],
palegreen: [152, 251, 152],
paleturquoise: [175, 238, 238],
palevioletred: [219, 112, 147],
papayawhip: [255, 239, 213],
peachpuff: [255, 218, 185],
peru: [205, 133, 63],
pink: [255, 192, 203],
plum: [221, 160, 221],
powderblue: [176, 224, 230],
purple: [128, 0, 128],
red: [255, 0, 0],
rosybrown: [188, 143, 143],
royalblue: [65, 105, 225],
saddlebrown: [139, 69, 19],
salmon: [250, 128, 114],
sandybrown: [244, 164, 96],
seagreen: [46, 139, 87],
seashell: [255, 245, 238],
sienna: [160, 82, 45],
silver: [192, 192, 192],
skyblue: [135, 206, 235],
slateblue: [106, 90, 205],
slategray: [112, 128, 144],
slategrey: [112, 128, 144],
snow: [255, 250, 250],
springgreen: [0, 255, 127],
steelblue: [70, 130, 180],
tan: [210, 180, 140],
teal: [0, 128, 128],
thistle: [216, 191, 216],
tomato: [255, 99, 71],
turquoise: [64, 224, 208],
violet: [238, 130, 238],
wheat: [245, 222, 179],
white: [255, 255, 255],
whitesmoke: [245, 245, 245],
yellow: [255, 255, 0],
yellowgreen: [154, 205, 50]
};
var setMap = function setMap(options) {
var obj = options.map;
var keys = options.keys;
var l = keys.length;
for (var i = 0; i < l; i++) {
var key = keys[i];
if (plainObject(key)) {
throw Error('Tried to set map with object key');
}
if (i < keys.length - 1) {
// extend the map if necessary
if (obj[key] == null) {
obj[key] = {};
}
obj = obj[key];
} else {
// set the value
obj[key] = options.value;
}
}
}; // gets the value in a map even if it's not built in places
var getMap = function getMap(options) {
var obj = options.map;
var keys = options.keys;
var l = keys.length;
for (var i = 0; i < l; i++) {
var key = keys[i];
if (plainObject(key)) {
throw Error('Tried to get map with object key');
}
obj = obj[key];
if (obj == null) {
return obj;
}
}
return obj;
}; // deletes the entry in the map
var performance = window$1 ? window$1.performance : null;
var pnow = performance && performance.now ? function () {
return performance.now();
} : function () {
return Date.now();
};
var raf = function () {
if (window$1) {
if (window$1.requestAnimationFrame) {
return function (fn) {
window$1.requestAnimationFrame(fn);
};
} else if (window$1.mozRequestAnimationFrame) {
return function (fn) {
window$1.mozRequestAnimationFrame(fn);
};
} else if (window$1.webkitRequestAnimationFrame) {
return function (fn) {
window$1.webkitRequestAnimationFrame(fn);
};
} else if (window$1.msRequestAnimationFrame) {
return function (fn) {
window$1.msRequestAnimationFrame(fn);
};
}
}
return function (fn) {
if (fn) {
setTimeout(function () {
fn(pnow());
}, 1000 / 60);
}
};
}();
var requestAnimationFrame = function requestAnimationFrame(fn) {
return raf(fn);
};
var performanceNow = pnow;
var DEFAULT_HASH_SEED = 9261;
var K = 65599; // 37 also works pretty well
var DEFAULT_HASH_SEED_ALT = 5381;
var hashIterableInts = function hashIterableInts(iterator) {
var seed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_HASH_SEED;
// sdbm/string-hash
var hash = seed;
var entry;
for (;;) {
entry = iterator.next();
if (entry.done) {
break;
}
hash = hash * K + entry.value | 0;
}
return hash;
};
var hashInt = function hashInt(num) {
var seed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_HASH_SEED;
// sdbm/string-hash
return seed * K + num | 0;
};
var hashIntAlt = function hashIntAlt(num) {
var seed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_HASH_SEED_ALT;
// djb2/string-hash
return (seed << 5) + seed + num | 0;
};
var combineHashes = function combineHashes(hash1, hash2) {
return hash1 * 0x200000 + hash2;
};
var combineHashesArray = function combineHashesArray(hashes) {
return hashes[0] * 0x200000 + hashes[1];
};
var hashArrays = function hashArrays(hashes1, hashes2) {
return [hashInt(hashes1[0], hashes2[0]), hashIntAlt(hashes1[1], hashes2[1])];
};
var hashIntsArray = function hashIntsArray(ints, seed) {
var entry = {
value: 0,
done: false
};
var i = 0;
var length = ints.length;
var iterator = {
next: function next() {
if (i < length) {
entry.value = ints[i++];
} else {
entry.done = true;
}
return entry;
}
};
return hashIterableInts(iterator, seed);
};
var hashString = function hashString(str, seed) {
var entry = {
value: 0,
done: false
};
var i = 0;
var length = str.length;
var iterator = {
next: function next() {
if (i < length) {
entry.value = str.charCodeAt(i++);
} else {
entry.done = true;
}
return entry;
}
};
return hashIterableInts(iterator, seed);
};
var hashStrings = function hashStrings() {
return hashStringsArray(arguments);
};
var hashStringsArray = function hashStringsArray(strs) {
var hash;
for (var i = 0; i < strs.length; i++) {
var str = strs[i];
if (i === 0) {
hash = hashString(str);
} else {
hash = hashString(str, hash);
}
}
return hash;
};
/*global console */
var warningsEnabled = true;
var warnSupported = console.warn != null; // eslint-disable-line no-console
var traceSupported = console.trace != null; // eslint-disable-line no-console
var MAX_INT$1 = Number.MAX_SAFE_INTEGER || 9007199254740991;
var trueify = function trueify() {
return true;
};
var falsify = function falsify() {
return false;
};
var zeroify = function zeroify() {
return 0;
};
var noop$1 = function noop() {};
var error = function error(msg) {
throw new Error(msg);
};
var warnings = function warnings(enabled) {
if (enabled !== undefined) {
warningsEnabled = !!enabled;
} else {
return warningsEnabled;
}
};
var warn = function warn(msg) {
/* eslint-disable no-console */
if (!warnings()) {
return;
}
if (warnSupported) {
console.warn(msg);
} else {
console.log(msg);
if (traceSupported) {
console.trace();
}
}
};
/* eslint-enable */
var clone = function clone(obj) {
return extend({}, obj);
}; // gets a shallow copy of the argument
var copy = function copy(obj) {
if (obj == null) {
return obj;
}
if (array(obj)) {
return obj.slice();
} else if (plainObject(obj)) {
return clone(obj);
} else {
return obj;
}
};
var copyArray = function copyArray(arr) {
return arr.slice();
};
var uuid = function uuid(a, b
/* placeholders */
) {
for ( // loop :)
b = a = ''; // b - result , a - numeric letiable
a++ < 36; //
b += a * 51 & 52 // if "a" is not 9 or 14 or 19 or 24
? // return a random number or 4
(a ^ 15 // if "a" is not 15
? // generate a random number from 0 to 15
8 ^ Math.random() * (a ^ 20 ? 16 : 4) // unless "a" is 20, in which case a random number from 8 to 11
: 4 // otherwise 4
).toString(16) : '-' // in other cases (if "a" is 9,14,19,24) insert "-"
) {
}
return b;
};
var _staticEmptyObject = {};
var staticEmptyObject = function staticEmptyObject() {
return _staticEmptyObject;
};
var defaults$g = function defaults(_defaults) {
var keys = Object.keys(_defaults);
return function (opts) {
var filledOpts = {};
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var optVal = opts == null ? undefined : opts[key];
filledOpts[key] = optVal === undefined ? _defaults[key] : optVal;
}
return filledOpts;
};
};
var removeFromArray = function removeFromArray(arr, ele, oneCopy) {
for (var i = arr.length - 1; i >= 0; i--) {
if (arr[i] === ele) {
arr.splice(i, 1);
if (oneCopy) {
break;
}
}
}
};
var clearArray = function clearArray(arr) {
arr.splice(0, arr.length);
};
var push = function push(arr, otherArr) {
for (var i = 0; i < otherArr.length; i++) {
var el = otherArr[i];
arr.push(el);
}
};
var getPrefixedProperty = function getPrefixedProperty(obj, propName, prefix) {
if (prefix) {
propName = prependCamel(prefix, propName); // e.g. (labelWidth, source) => sourceLabelWidth
}
return obj[propName];
};
var setPrefixedProperty = function setPrefixedProperty(obj, propName, prefix, value) {
if (prefix) {
propName = prependCamel(prefix, propName); // e.g. (labelWidth, source) => sourceLabelWidth
}
obj[propName] = value;
};
/* global Map */
var ObjectMap = /*#__PURE__*/function () {
function ObjectMap() {
_classCallCheck(this, ObjectMap);
this._obj = {};
}
_createClass(ObjectMap, [{
key: "set",
value: function set(key, val) {
this._obj[key] = val;
return this;
}
}, {
key: "delete",
value: function _delete(key) {
this._obj[key] = undefined;
return this;
}
}, {
key: "clear",
value: function clear() {
this._obj = {};
}
}, {
key: "has",
value: function has(key) {
return this._obj[key] !== undefined;
}
}, {
key: "get",
value: function get(key) {
return this._obj[key];
}
}]);
return ObjectMap;
}();
var Map$1 = typeof Map !== 'undefined' ? Map : ObjectMap;
/* global Set */
var undef = "undefined" ;
var ObjectSet = /*#__PURE__*/function () {
function ObjectSet(arrayOrObjectSet) {
_classCallCheck(this, ObjectSet);
this._obj = Object.create(null);
this.size = 0;
if (arrayOrObjectSet != null) {
var arr;
if (arrayOrObjectSet.instanceString != null && arrayOrObjectSet.instanceString() === this.instanceString()) {
arr = arrayOrObjectSet.toArray();
} else {
arr = arrayOrObjectSet;
}
for (var i = 0; i < arr.length; i++) {
this.add(arr[i]);
}
}
}
_createClass(ObjectSet, [{
key: "instanceString",
value: function instanceString() {
return 'set';
}
}, {
key: "add",
value: function add(val) {
var o = this._obj;
if (o[val] !== 1) {
o[val] = 1;
this.size++;
}
}
}, {
key: "delete",
value: function _delete(val) {
var o = this._obj;
if (o[val] === 1) {
o[val] = 0;
this.size--;
}
}
}, {
key: "clear",
value: function clear() {
this._obj = Object.create(null);
}
}, {
key: "has",
value: function has(val) {
return this._obj[val] === 1;
}
}, {
key: "toArray",
value: function toArray() {
var _this = this;
return Object.keys(this._obj).filter(function (key) {
return _this.has(key);
});
}
}, {
key: "forEach",
value: function forEach(callback, thisArg) {
return this.toArray().forEach(callback, thisArg);
}
}]);
return ObjectSet;
}();
var Set$1 = (typeof Set === "undefined" ? "undefined" : _typeof(Set)) !== undef ? Set : ObjectSet;
var Element = function Element(cy, params) {
var restore = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
if (cy === undefined || params === undefined || !core(cy)) {
error('An element must have a core reference and parameters set');
return;
}
var group = params.group; // try to automatically infer the group if unspecified
if (group == null) {
if (params.data && params.data.source != null && params.data.target != null) {
group = 'edges';
} else {
group = 'nodes';
}
} // validate group
if (group !== 'nodes' && group !== 'edges') {
error('An element must be of type `nodes` or `edges`; you specified `' + group + '`');
return;
} // make the element array-like, just like a collection
this.length = 1;
this[0] = this; // NOTE: when something is added here, add also to ele.json()
var _p = this._private = {
cy: cy,
single: true,
// indicates this is an element
data: params.data || {},
// data object
position: params.position || {
x: 0,
y: 0
},
// (x, y) position pair
autoWidth: undefined,
// width and height of nodes calculated by the renderer when set to special 'auto' value
autoHeight: undefined,
autoPadding: undefined,
compoundBoundsClean: false,
// whether the compound dimensions need to be recalculated the next time dimensions are read
listeners: [],
// array of bound listeners
group: group,
// string; 'nodes' or 'edges'
style: {},
// properties as set by the style
rstyle: {},
// properties for style sent from the renderer to the core
styleCxts: [],
// applied style contexts from the styler
styleKeys: {},
// per-group keys of style property values
removed: true,
// whether it's inside the vis; true if removed (set true here since we call restore)
selected: params.selected ? true : false,
// whether it's selected
selectable: params.selectable === undefined ? true : params.selectable ? true : false,
// whether it's selectable
locked: params.locked ? true : false,
// whether the element is locked (cannot be moved)
grabbed: false,
// whether the element is grabbed by the mouse; renderer sets this privately
grabbable: params.grabbable === undefined ? true : params.grabbable ? true : false,
// whether the element can be grabbed
pannable: params.pannable === undefined ? group === 'edges' ? true : false : params.pannable ? true : false,
// whether the element has passthrough panning enabled
active: false,
// whether the element is active from user interaction
classes: new Set$1(),
// map ( className => true )
animation: {
// object for currently-running animations
current: [],
queue: []
},
rscratch: {},
// object in which the renderer can store information
scratch: params.scratch || {},
// scratch objects
edges: [],
// array of connected edges
children: [],
// array of children
parent: params.parent && params.parent.isNode() ? params.parent : null,
// parent ref
traversalCache: {},
// cache of output of traversal functions
backgrounding: false,
// whether background images are loading
bbCache: null,
// cache of the current bounding box
bbCacheShift: {
x: 0,
y: 0
},
// shift applied to cached bb to be applied on next get
bodyBounds: null,
// bounds cache of element body, w/o overlay
overlayBounds: null,
// bounds cache of element body, including overlay
labelBounds: {
// bounds cache of labels
all: null,
source: null,
target: null,
main: null
},
arrowBounds: {
// bounds cache of edge arrows
source: null,
target: null,
'mid-source': null,
'mid-target': null
}
};
if (_p.position.x == null) {
_p.position.x = 0;
}
if (_p.position.y == null) {
_p.position.y = 0;
} // renderedPosition overrides if specified
if (params.renderedPosition) {
var rpos = params.renderedPosition;
var pan = cy.pan();
var zoom = cy.zoom();
_p.position = {
x: (rpos.x - pan.x) / zoom,
y: (rpos.y - pan.y) / zoom
};
}
var classes = [];
if (array(params.classes)) {
classes = params.classes;
} else if (string(params.classes)) {
classes = params.classes.split(/\s+/);
}
for (var i = 0, l = classes.length; i < l; i++) {
var cls = classes[i];
if (!cls || cls === '') {
continue;
}
_p.classes.add(cls);
}
this.createEmitter();
var bypass = params.style || params.css;
if (bypass) {
warn('Setting a `style` bypass at element creation should be done only when absolutely necessary. Try to use the stylesheet instead.');
this.style(bypass);
}
if (restore === undefined || restore) {
this.restore();
}
};
var defineSearch = function defineSearch(params) {
params = {
bfs: params.bfs || !params.dfs,
dfs: params.dfs || !params.bfs
}; // from pseudocode on wikipedia
return function searchFn(roots, fn, directed) {
var options;
if (plainObject(roots) && !elementOrCollection(roots)) {
options = roots;
roots = options.roots || options.root;
fn = options.visit;
directed = options.directed;
}
directed = arguments.length === 2 && !fn$6(fn) ? fn : directed;
fn = fn$6(fn) ? fn : function () {};
var cy = this._private.cy;
var v = roots = string(roots) ? this.filter(roots) : roots;
var Q = [];
var connectedNodes = [];
var connectedBy = {};
var id2depth = {};
var V = {};
var j = 0;
var found;
var _this$byGroup = this.byGroup(),
nodes = _this$byGroup.nodes,
edges = _this$byGroup.edges; // enqueue v
for (var i = 0; i < v.length; i++) {
var vi = v[i];
var viId = vi.id();
if (vi.isNode()) {
Q.unshift(vi);
if (params.bfs) {
V[viId] = true;
connectedNodes.push(vi);
}
id2depth[viId] = 0;
}
}
var _loop = function _loop() {
var v = params.bfs ? Q.shift() : Q.pop();
var vId = v.id();
if (params.dfs) {
if (V[vId]) {
return "continue";
}
V[vId] = true;
connectedNodes.push(v);
}
var depth = id2depth[vId];
var prevEdge = connectedBy[vId];
var src = prevEdge != null ? prevEdge.source() : null;
var tgt = prevEdge != null ? prevEdge.target() : null;
var prevNode = prevEdge == null ? undefined : v.same(src) ? tgt[0] : src[0];
var ret = void 0;
ret = fn(v, prevEdge, prevNode, j++, depth);
if (ret === true) {
found = v;
return "break";
}
if (ret === false) {
return "break";
}
var vwEdges = v.connectedEdges().filter(function (e) {
return (!directed || e.source().same(v)) && edges.has(e);
});
for (var _i2 = 0; _i2 < vwEdges.length; _i2++) {
var e = vwEdges[_i2];
var w = e.connectedNodes().filter(function (n) {
return !n.same(v) && nodes.has(n);
});
var wId = w.id();
if (w.length !== 0 && !V[wId]) {
w = w[0];
Q.push(w);
if (params.bfs) {
V[wId] = true;
connectedNodes.push(w);
}
connectedBy[wId] = e;
id2depth[wId] = id2depth[vId] + 1;
}
}
};
while (Q.length !== 0) {
var _ret = _loop();
if (_ret === "continue") continue;
if (_ret === "break") break;
}
var connectedEles = cy.collection();
for (var _i = 0; _i < connectedNodes.length; _i++) {
var node = connectedNodes[_i];
var edge = connectedBy[node.id()];
if (edge != null) {
connectedEles.push(edge);
}
connectedEles.push(node);
}
return {
path: cy.collection(connectedEles),
found: cy.collection(found)
};
};
}; // search, spanning trees, etc
var elesfn$v = {
breadthFirstSearch: defineSearch({
bfs: true
}),
depthFirstSearch: defineSearch({
dfs: true
})
}; // nice, short mathematical alias
elesfn$v.bfs = elesfn$v.breadthFirstSearch;
elesfn$v.dfs = elesfn$v.depthFirstSearch;
var dijkstraDefaults = defaults$g({
root: null,
weight: function weight(edge) {
return 1;
},
directed: false
});
var elesfn$u = {
dijkstra: function dijkstra(options) {
if (!plainObject(options)) {
var args = arguments;
options = {
root: args[0],
weight: args[1],
directed: args[2]
};
}
var _dijkstraDefaults = dijkstraDefaults(options),
root = _dijkstraDefaults.root,
weight = _dijkstraDefaults.weight,
directed = _dijkstraDefaults.directed;
var eles = this;
var weightFn = weight;
var source = string(root) ? this.filter(root)[0] : root[0];
var dist = {};
var prev = {};
var knownDist = {};
var _this$byGroup = this.byGroup(),
nodes = _this$byGroup.nodes,
edges = _this$byGroup.edges;
edges.unmergeBy(function (ele) {
return ele.isLoop();
});
var getDist = function getDist(node) {
return dist[node.id()];
};
var setDist = function setDist(node, d) {
dist[node.id()] = d;
Q.updateItem(node);
};
var Q = new Heap__default["default"](function (a, b) {
return getDist(a) - getDist(b);
});
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i];
dist[node.id()] = node.same(source) ? 0 : Infinity;
Q.push(node);
}
var distBetween = function distBetween(u, v) {
var uvs = (directed ? u.edgesTo(v) : u.edgesWith(v)).intersect(edges);
var smallestDistance = Infinity;
var smallestEdge;
for (var _i = 0; _i < uvs.length; _i++) {
var edge = uvs[_i];
var _weight = weightFn(edge);
if (_weight < smallestDistance || !smallestEdge) {
smallestDistance = _weight;
smallestEdge = edge;
}
}
return {
edge: smallestEdge,
dist: smallestDistance
};
};
while (Q.size() > 0) {
var u = Q.pop();
var smalletsDist = getDist(u);
var uid = u.id();
knownDist[uid] = smalletsDist;
if (smalletsDist === Infinity) {
continue;
}
var neighbors = u.neighborhood().intersect(nodes);
for (var _i2 = 0; _i2 < neighbors.length; _i2++) {
var v = neighbors[_i2];
var vid = v.id();
var vDist = distBetween(u, v);
var alt = smalletsDist + vDist.dist;
if (alt < getDist(v)) {
setDist(v, alt);
prev[vid] = {
node: u,
edge: vDist.edge
};
}
} // for
} // while
return {
distanceTo: function distanceTo(node) {
var target = string(node) ? nodes.filter(node)[0] : node[0];
return knownDist[target.id()];
},
pathTo: function pathTo(node) {
var target = string(node) ? nodes.filter(node)[0] : node[0];
var S = [];
var u = target;
var uid = u.id();
if (target.length > 0) {
S.unshift(target);
while (prev[uid]) {
var p = prev[uid];
S.unshift(p.edge);
S.unshift(p.node);
u = p.node;
uid = u.id();
}
}
return eles.spawn(S);
}
};
}
};
var elesfn$t = {
// kruskal's algorithm (finds min spanning tree, assuming undirected graph)
// implemented from pseudocode from wikipedia
kruskal: function kruskal(weightFn) {
weightFn = weightFn || function (edge) {
return 1;
};
var _this$byGroup = this.byGroup(),
nodes = _this$byGroup.nodes,
edges = _this$byGroup.edges;
var numNodes = nodes.length;
var forest = new Array(numNodes);
var A = nodes; // assumes byGroup() creates new collections that can be safely mutated
var findSetIndex = function findSetIndex(ele) {
for (var i = 0; i < forest.length; i++) {
var eles = forest[i];
if (eles.has(ele)) {
return i;
}
}
}; // start with one forest per node
for (var i = 0; i < numNodes; i++) {
forest[i] = this.spawn(nodes[i]);
}
var S = edges.sort(function (a, b) {
return weightFn(a) - weightFn(b);
});
for (var _i = 0; _i < S.length; _i++) {
var edge = S[_i];
var u = edge.source()[0];
var v = edge.target()[0];
var setUIndex = findSetIndex(u);
var setVIndex = findSetIndex(v);
var setU = forest[setUIndex];
var setV = forest[setVIndex];
if (setUIndex !== setVIndex) {
A.merge(edge); // combine forests for u and v
setU.merge(setV);
forest.splice(setVIndex, 1);
}
}
return A;
}
};
var aStarDefaults = defaults$g({
root: null,
goal: null,
weight: function weight(edge) {
return 1;
},
heuristic: function heuristic(edge) {
return 0;
},
directed: false
});
var elesfn$s = {
// Implemented from pseudocode from wikipedia
aStar: function aStar(options) {
var cy = this.cy();
var _aStarDefaults = aStarDefaults(options),
root = _aStarDefaults.root,
goal = _aStarDefaults.goal,
heuristic = _aStarDefaults.heuristic,
directed = _aStarDefaults.directed,
weight = _aStarDefaults.weight;
root = cy.collection(root)[0];
goal = cy.collection(goal)[0];
var sid = root.id();
var tid = goal.id();
var gScore = {};
var fScore = {};
var closedSetIds = {};
var openSet = new Heap__default["default"](function (a, b) {
return fScore[a.id()] - fScore[b.id()];
});
var openSetIds = new Set$1();
var cameFrom = {};
var cameFromEdge = {};
var addToOpenSet = function addToOpenSet(ele, id) {
openSet.push(ele);
openSetIds.add(id);
};
var cMin, cMinId;
var popFromOpenSet = function popFromOpenSet() {
cMin = openSet.pop();
cMinId = cMin.id();
openSetIds["delete"](cMinId);
};
var isInOpenSet = function isInOpenSet(id) {
return openSetIds.has(id);
};
addToOpenSet(root, sid);
gScore[sid] = 0;
fScore[sid] = heuristic(root); // Counter
var steps = 0; // Main loop
while (openSet.size() > 0) {
popFromOpenSet();
steps++; // If we've found our goal, then we are done
if (cMinId === tid) {
var path = [];
var pathNode = goal;
var pathNodeId = tid;
var pathEdge = cameFromEdge[pathNodeId];
for (;;) {
path.unshift(pathNode);
if (pathEdge != null) {
path.unshift(pathEdge);
}
pathNode = cameFrom[pathNodeId];
if (pathNode == null) {
break;
}
pathNodeId = pathNode.id();
pathEdge = cameFromEdge[pathNodeId];
}
return {
found: true,
distance: gScore[cMinId],
path: this.spawn(path),
steps: steps
};
} // Add cMin to processed nodes
closedSetIds[cMinId] = true; // Update scores for neighbors of cMin
// Take into account if graph is directed or not
var vwEdges = cMin._private.edges;
for (var i = 0; i < vwEdges.length; i++) {
var e = vwEdges[i]; // edge must be in set of calling eles
if (!this.hasElementWithId(e.id())) {
continue;
} // cMin must be the source of edge if directed
if (directed && e.data('source') !== cMinId) {
continue;
}
var wSrc = e.source();
var wTgt = e.target();
var w = wSrc.id() !== cMinId ? wSrc : wTgt;
var wid = w.id(); // node must be in set of calling eles
if (!this.hasElementWithId(wid)) {
continue;
} // if node is in closedSet, ignore it
if (closedSetIds[wid]) {
continue;
} // New tentative score for node w
var tempScore = gScore[cMinId] + weight(e); // Update gScore for node w if:
// w not present in openSet
// OR
// tentative gScore is less than previous value
// w not in openSet
if (!isInOpenSet(wid)) {
gScore[wid] = tempScore;
fScore[wid] = tempScore + heuristic(w);
addToOpenSet(w, wid);
cameFrom[wid] = cMin;
cameFromEdge[wid] = e;
continue;
} // w already in openSet, but with greater gScore
if (tempScore < gScore[wid]) {
gScore[wid] = tempScore;
fScore[wid] = tempScore + heuristic(w);
cameFrom[wid] = cMin;
cameFromEdge[wid] = e;
}
} // End of neighbors update
} // End of main loop
// If we've reached here, then we've not reached our goal
return {
found: false,
distance: undefined,
path: undefined,
steps: steps
};
}
}; // elesfn
var floydWarshallDefaults = defaults$g({
weight: function weight(edge) {
return 1;
},
directed: false
});
var elesfn$r = {
// Implemented from pseudocode from wikipedia
floydWarshall: function floydWarshall(options) {
var cy = this.cy();
var _floydWarshallDefault = floydWarshallDefaults(options),
weight = _floydWarshallDefault.weight,
directed = _floydWarshallDefault.directed;
var weightFn = weight;
var _this$byGroup = this.byGroup(),
nodes = _this$byGroup.nodes,
edges = _this$byGroup.edges;
var N = nodes.length;
var Nsq = N * N;
var indexOf = function indexOf(node) {
return nodes.indexOf(node);
};
var atIndex = function atIndex(i) {
return nodes[i];
}; // Initialize distance matrix
var dist = new Array(Nsq);
for (var n = 0; n < Nsq; n++) {
var j = n % N;
var i = (n - j) / N;
if (i === j) {
dist[n] = 0;
} else {
dist[n] = Infinity;
}
} // Initialize matrix used for path reconstruction
// Initialize distance matrix
var next = new Array(Nsq);
var edgeNext = new Array(Nsq); // Process edges
for (var _i = 0; _i < edges.length; _i++) {
var edge = edges[_i];
var src = edge.source()[0];
var tgt = edge.target()[0];
if (src === tgt) {
continue;
} // exclude loops
var s = indexOf(src);
var t = indexOf(tgt);
var st = s * N + t; // source to target index
var _weight = weightFn(edge); // Check if already process another edge between same 2 nodes
if (dist[st] > _weight) {
dist[st] = _weight;
next[st] = t;
edgeNext[st] = edge;
} // If undirected graph, process 'reversed' edge
if (!directed) {
var ts = t * N + s; // target to source index
if (!directed && dist[ts] > _weight) {
dist[ts] = _weight;
next[ts] = s;
edgeNext[ts] = edge;
}
}
} // Main loop
for (var k = 0; k < N; k++) {
for (var _i2 = 0; _i2 < N; _i2++) {
var ik = _i2 * N + k;
for (var _j = 0; _j < N; _j++) {
var ij = _i2 * N + _j;
var kj = k * N + _j;
if (dist[ik] + dist[kj] < dist[ij]) {
dist[ij] = dist[ik] + dist[kj];
next[ij] = next[ik];
}
}
}
}
var getArgEle = function getArgEle(ele) {
return (string(ele) ? cy.filter(ele) : ele)[0];
};
var indexOfArgEle = function indexOfArgEle(ele) {
return indexOf(getArgEle(ele));
};
var res = {
distance: function distance(from, to) {
var i = indexOfArgEle(from);
var j = indexOfArgEle(to);
return dist[i * N + j];
},
path: function path(from, to) {
var i = indexOfArgEle(from);
var j = indexOfArgEle(to);
var fromNode = atIndex(i);
if (i === j) {
return fromNode.collection();
}
if (next[i * N + j] == null) {
return cy.collection();
}
var path = cy.collection();
var prev = i;
var edge;
path.merge(fromNode);
while (i !== j) {
prev = i;
i = next[i * N + j];
edge = edgeNext[prev * N + i];
path.merge(edge);
path.merge(atIndex(i));
}
return path;
}
};
return res;
} // floydWarshall
}; // elesfn
var bellmanFordDefaults = defaults$g({
weight: function weight(edge) {
return 1;
},
directed: false,
root: null
});
var elesfn$q = {
// Implemented from pseudocode from wikipedia
bellmanFord: function bellmanFord(options) {
var _this = this;
var _bellmanFordDefaults = bellmanFordDefaults(options),
weight = _bellmanFordDefaults.weight,
directed = _bellmanFordDefaults.directed,
root = _bellmanFordDefaults.root;
var weightFn = weight;
var eles = this;
var cy = this.cy();
var _this$byGroup = this.byGroup(),
edges = _this$byGroup.edges,
nodes = _this$byGroup.nodes;
var numNodes = nodes.length;
var infoMap = new Map$1();
var hasNegativeWeightCycle = false;
var negativeWeightCycles = [];
root = cy.collection(root)[0]; // in case selector passed
edges.unmergeBy(function (edge) {
return edge.isLoop();
});
var numEdges = edges.length;
var getInfo = function getInfo(node) {
var obj = infoMap.get(node.id());
if (!obj) {
obj = {};
infoMap.set(node.id(), obj);
}
return obj;
};
var getNodeFromTo = function getNodeFromTo(to) {
return (string(to) ? cy.$(to) : to)[0];
};
var distanceTo = functi